如鹏网 大学生计算机学习社区

CowNew开源团队

http://www.cownew.com 邮件请联系 about521 at 163.com

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  363 随笔 :: 2 文章 :: 808 评论 :: 0 Trackbacks

#

     摘要: XML 技术是随着 Java 的发展而发展起来的。在 XML 出现之前对于简单的数据格式通常是存储在 ini 配置文件等文本文件中,复杂的格式则采用自定义的文件格式,因此对于每种文件格式都要有专门的解析程序。 XML 出现以后解决了这个问题,程序面对的是有固定格式的 XML 文件,只要通过...  阅读全文
posted @ 2007-03-26 13:14 CowNew开源团队 阅读(3394) | 评论 (5)编辑 收藏

     摘要: 是否选择了合适的数据结构进行数据处理对系统的性能有着极大的影响, JDK 中提供了常用的数据结构的实现类,比如链表、堆栈、哈希表,很多第三方开源库也进行了有益的扩展。关于这些类的原理以及使用可以参考相关的手册,在本节中重点讲解一些使用中需要注意的问题 。 1.1.1.       增量内存分配 ...  阅读全文
posted @ 2007-03-16 12:37 CowNew开源团队 阅读(1763) | 评论 (5)编辑 收藏

这是刚才和一个朋友的聊天记录,希望对大家有帮助:
佘士东 08:41:47
我设计一个接口,其中有些方法很类似,比如取得某个工作对象,有可能需要获得多个,也有可能获得其中一个,参数为工作对象的名字、名字列表。
我是用窄接口还是宽接口好,是用一个最大功能的方法还是多个重载方法好?
比如:
IService
public Worker  getWorker(String name);
public Vector<Worker> getWorkers(final Vector<String> names);
我是在接口约束这两个方法还是只约束最大的那个,使所有的方法都适配为后面这个最大方法,而在接口中去掉第一个方法
杨中科 08:51:57
我认为还是多个重载方法好,主要是考虑方便别人使用
 
杨中科 08:52:31
顺便说一句:为什么参数和返回值要用Vector?用List接口不更好吗?
 
佘士东 08:53:55
如果适用者很有限,大概只有5个左右,实际上使用者也是提供适配功能,比如使用cs结构,web方式,wap方式,sms方式获得接口服务的适配模块
佘士东 08:55:04
我的想法是使用Vector它是异步安全的,服务可能是多线程实现的,所以使用Vector返回,不知道有没有这个必要,有没有这个作用
杨中科 08:55:12
你说的是什么意思,不太明白。你说getworker方法不是所有实现类都能实现?
 
佘士东 08:56:35
其实这个接口是夹在实现和使用这中间的,使用者实现不同类型服务的适配,实现根据项目不同所要求的业务实现不一样,实际上这个接口是约束实现要多
佘士东 08:58:08
如果接口方法太多,我怕如果变更会不会陷入变更里面,因为重载多了,其中很多有重复,比如参数列表,如果需要加上用户验证,那就都要加,这样所有实现都要改动一批
杨中科 08:59:41
“我的想法是使用Vector它是异步安全的,服务可能是多线程实现的,所以使用Vector返回,不知道有没有这个必要,有没有这个作用 ”,你可以将传进来的List参数用Collections类中的syn****List方法将List搞成异步安全的,返回的时候你也可以返回Vector类型的,但是返回值要生命成List类型
 
杨中科 09:00:14
要考虑二次开发人员的易用性,大部分人还是倾向于使用List、ArrayList这样的东西的
 
杨中科 09:01:50
“如果接口方法太多,我怕如果变更会不会陷入变更里面,因为重载多了,其中很多有重复,比如参数列表,如果需要加上用户验证,那就都要加,这样所有实现都要改动一批 ”,还是那句话,不要陷入实现的漩涡中,你的接口是声明服务用的,不要管实现,怎么实现是实现类的事情,站在二次开发人员的角度来看你必须同时提供getworker和getworkers两个方法
 
佘士东 09:01:49
原来如此,就是说实际上还是Vector,只不过返回值使用List接口,但是如果他直接转换成ArrayList使用会不会丢掉原来异步安全特性?因为返回值毕竟只是一个引用,可能其它地方也在用同一个引用
杨中科 09:02:30
不可能转换为ArrayList的,否则运行的时候会抛ClassCastException
 
佘士东 09:02:46
但是,二次开发实际上是开发实现类,而不是服务调用类
杨中科 09:03:24
哦,也就是二次开发实际上是写一个实现了你定义的接口的插件???
 
佘士东 09:03:47
对,就是这个意思
杨中科 09:04:57
那也最好提供这两个接口,这样你使用这些插件的时候也方便,你可以写一个抽象类来实现默认的getworker方法,在getworker中调用getworkers方法,这样二次开发人员一般只要实现getworkers方法就可以了
 
佘士东 09:04:57
但是这个插件是惟一的,使用一个Factory获得实现
佘士东 09:05:57
哈哈,豁然开朗,宽接口,加上适配抽象父类,就搞定了
杨中科 09:06:26
接口方法是越多用起来越方便
 
佘士东 09:07:10
我只是怕在产生变更的时候,对应的实现也要改动很多,毕竟框架才是初期
杨中科 09:08:29
“对应的实现也要改动很多”,那就看你抽象类的实现水平的,定义接口的时候不要去想实现,只要想接口定义那些方法才够用就可以,实现和接口不能混
 
杨中科 09:09:00
你可以用各种设计模式来保证不会发生“产生变更的时候,对应的实现也要改动很多”
 
杨中科 09:09:11
但是接口就是接口

posted @ 2007-03-13 09:18 CowNew开源团队 阅读(1959) | 评论 (10)编辑 收藏

Python 的模块一旦加载就会常驻内存,直到程序结束。再碰到 import 语句式只是修改名字空间,而不需要重新加载。这种机制是出于运行时的效率考虑,每遇到 import 的时候重新加载显然很低效。它也不会检查源文件的修改时间以确定是否重新加载,Python 有那么多的模块,每次调用时都检查一遍时间也是不行的。

这种机制下,开发长时间运行的守护程序就会很麻烦,修改源代码后要重新启动程序才能让新的代码生效。比如用 mod_python 做 web 开发,Apache 会启动多个守护进程来应答客户请求,里面有 python 的解释引擎和加载的模块,若要让修改后的代码生效只能重起 apache,这会影响到其它服务的正常运行,非常不方便。mod_python 有一个PythonAutoReload 参数,它只是针对 PythonHandler 而言的,能够对设定的 PythonHandler 实现自动重新加载,而该 Handler 中所用到的模块却不能自动 reload。

这种修改源代码然后重起 apache 的调试方式实在让我无法忍受了,决定实现一种自动重新加载机制。基本的思路就是每个用户请求到来时,检查我所关心的那些模块源文件的修改时间,如果比加载时的修改时间新,则重新加载。

编写一个检测时间和重新加载的函数,让它在每个请求到来时执行:

  1. def  autoreload():   
  2.   mod_names = ['Entry','Index','SideBar']   
  3.    for  mod_name  in  mod_names:   
  4.      try :   
  5.       module =  sys .modules[ mod_name ]   
  6.      except :   
  7.        continue   
  8.     mtime =  os .path.getmtime( module.__file__ )   
  9.      try :   
  10.        if  mtime > module.loadtime:   
  11.          reload ( module )   
  12.      except :   
  13.      pass   
  14.     module.loadtime = mtime   

这段代码不长,但是改了好多个版本,最开始用 has_key() 的方式来检测是否存在某个模块,检测该模块是否有 loadtime 属性( 用 module.__dict__ ),现在这种方式应该效率高一些,曾经在一个 blog 上看到过对比测试数据。起初还在每个关心的模块里面加上一句loadtime = os.path.getmtime( __file__ ),这是不必要的,因为 Python 用的是动态类型,可以在运行时追加属性,第一次检测时设置初始状态即可。

有了这段代码,开发 BlogXP 方便多了,改了源码之后立马就能生效,而且它在正常运行时的消耗也很小。另外,由于mod_python 能够实现指定的 Handler 的自动重新加载,将这段代码放在该 Handler 中,可以方便地改变所关心的模块列表,也不需重起 apache。

欢迎批评指正:-)
from: http://blog.daviesliu.net/article/entry20050610-235635

posted @ 2007-03-12 14:57 CowNew开源团队 阅读(1725) | 评论 (2)编辑 收藏

thanks to hengheng123456789:
首席执行官『ceo.icxo.com』专家指点:30岁前让你成为“富翁”的四大秘诀

 内修工夫+外营人脉

    所谓,只能靠钱赚钱?尽管市面上理财书籍教的致富方法,大多是以投资工具为媒介,但积累资产的方法不只一种,有人懂得善用投资工具,大赚机会财;有人则专营人脉圈,年轻时愿意多付点交际费当学费,先蹲后跳,随之而来的是职位、薪水的提升以及见识的增广,已经不是可以用报酬率这类数字来衡量的了。

    外营:深耕职场关系

    上世纪九十年代初就开始投资的李雨,对于理财工具的知识比一般人还要强,却没有用于自己的资产规划,“我没有很刻意存钱或寻求投资,我认为投资自己最重要!”他说:李雨对自我的投资,包含了进修与人脉两项。他曾在上海一家最高级的休闲俱乐部待了7年,做到市场总监,举办过数十场的大型休闲运动赛事,招待过阿加西、张德培等世界运动名将。

  有些俱乐部是达官贵人的汇聚之所,在那里可以接触到很多优秀的人。李雨从一个小专员开始,只有一千多元的薪水,他却舍得请客吃饭、多结交朋友,而非存起来。“你知道吗?光听他们讲话就觉得收获颇丰!”他觉得这交际费花得太值了。他的专业是市场营销,深耕人脉的作用很快便“发酵”般扩散,各方人士大力赞助并参与他所举办的活动。不过三年,他便跻身年薪百万一族了。

    李雨实行的就是“人脉理财法”:藉由结识比自己更优秀的人才,协助事业或眼界的拓展。理财专家也认为:投资在理财的时间愈长就表示投资在自己身上的时间愈短,而增加自己这个“人力资本”,如增加学历、才能、提升工作技能与人际关系,比投资所得的利息更多。这个建议特别适合初入社会三五年的青年,正逢职涯起步,最重要的是积累专业知识与建立职场关系,与其算计一些蝇头小利,倒不如将时间成本花在经营本业,工作表现好,升官加薪也不远了。

    内修:打响自我口碑

    人脉理财,需要真才实学相辅相成,指的是专业知识与敬业态度。在工作上肯下苦工是第一步,博得客户、上司、同事的信任,先有工作表现为基础,人脉的加分效果才明显。

    27岁的杨庆,前一份工作是精品公关公司的专员,如今,则是国内某知名钟表代理公司的公关经理。当初尚未正式上班,公司就送来一支市价20万的名表当作员工福利。不少人欣羡她能得到这个好职位,杨庆则说获得职涯攀升的机会连自己都觉得意外,因为是老板主动找上她的。

    原来现在的老板曾经是她的客户,认同杨庆的办事能力;当底下有缺,便将她列为候选人之一。而之所以被公司选中,“后来我才知道,老板曾问过几位媒体记者的意见,最后选了我。”由于她与媒体接洽时,会针对不同属性的媒体提供多元的新闻角度,这份努力让记者肯定其专业,若有人问起杨庆的工作能力,想必多是美言。往往就是因为共事的好印象,就算没有刻意经营关系,无形之中也帮你牵起好人脉,因此实力与人脉的养成不能偏废。

 真诚付出,心薪相印

    “人脉理财法”并不适合急欲一步登天的人,关系是一种长期投资,要细火慢炖,谁也算不准它在何时才开花结果,甚至要有心理准备,不一定有职位、薪资等实质回馈。

    人脉的回馈是以各种形式展现在你的生涯中。结识优秀的人就像李雨所说,听他们讲话都有收获!当你面对人生关卡、遭遇困境之际,往往能从好的人脉那儿得到指引和帮助,他们或许无法在事业上给予直接帮助(通常若你值得信任,他们必会拔刀相助),但有时一句话就让你受益无穷。

    而最会经营人脉者都不约而同地透露:与人结交,真心为贵。美国知名企业家与激发潜能大师博恩崔西(Brain Tracy)指导学员销售成功术时,最常挂在嘴边的就是“真诚地关怀你的顾客”。他说:“你越关怀你的顾客,他们就越有兴趣跟你做生意,一旦客户认定你是真心关怀他的处境,不论销售的细节或竞争者如何,他都会向你购买。”做成生意只是结果,崔西教导的重点是以真诚赢得人心。

posted @ 2007-03-09 16:58 CowNew开源团队 阅读(377) | 评论 (0)编辑 收藏

这是今天早晨我和一个网友关于eclipse调试原理的聊天记录,希望对大家有帮助:
小鱼 说:
你说了解JAVA的编译机制和熟练使用调试,最好的方法是不是去阅读eclipse的源代码啊
杨中科 说:
编译机制?要了解编译机制的话最先肯定要把编译原理搞清楚呀,eclipse本身是不负责编译java代码的,它是委托给JDK去编译的,因此要了解java的编译机制肯定要去阅读jdk的源码的
杨中科 说:
不过jdk的编译器部分的源码好像没有开放
杨中科 说:
使用调试也不用去看源码,功能很简单的
小鱼 说:
是啊,我觉得eclipse的调试很有用啊,尤其是你以前讲过的那个jsp的调试,学问很深啊
杨中科 说:
原理上并不难,因为eclipse是把调试请求通过jpda协议发给jdk来完成的,eclipse本身不提供java代码的编译和调试机制
小鱼 说:
这就是实时监测虚拟机的运行状态吧
杨中科 说:
不过读懂了eclipse的java调试部分的代码你就也可以写出一个java的调试器出来
小鱼 说:
断点就是给程序一个中断是吧?
小鱼 说:
是的
杨中科 说:
不是实时检测,是一个请求、应答的模式
杨中科 说:
比如我们在java的编译器的第五行放了一个断点,那么代码调试起来以后,eclipse就告诉运行环境“请在第五行停下来”,那么运行环境就会在第五行停下来。然后你想看看i这个变量的值,eclipse就会向运行环境请求“请告诉我i等于多少”,然后运行环境就将i的值告诉eclipse,eclipse就将这个值显示给你。原理非常简单
小鱼 说:
也就是程序挂起吧?
杨中科 说:
eclipse只是充当了一个介绍人的角色
杨中科 说:
不明白程序挂起具体指的什么,不过应该就是你理解的意思
小鱼 说:
也是,一个和用户直接打交道的UI

杨中科 说:

http://www.blogjava.net/huanzhugege/

 

posted @ 2007-03-07 09:13 CowNew开源团队 阅读(2518) | 评论 (1)编辑 收藏

   在开发过程中我发现终端屏幕频繁的刷新,看上去闪的厉害。使用截包工具(我用的是EtherDetect Packet Sniffer,在Sniffer单机端口数据的时候比Sniffer Pro易用)分析发现,每次更新一个子窗口的时候竟然整个屏幕都被刷新了,数据量非常大。为了发现问题,我编写了下面的测试程序:
from ACursesEX import *
import curses

def main():
    mainwin = curses.newwin(15,50,0,0)
    mainwin.box()
   
    mainwin.addstr(0,0,"主窗口")
    mainwin.refresh()
   
    cwin = curses.newwin(5,20,2,2)
    cwin.addstr(1,1,"子窗口")
    cwin.box()
    cwin.refresh()
    while(True):
        ch = cwin.getch()
        cwin.clear()
        cwin.addch(2,1,ch)
        cwin.touchwin()
        cwin.refresh()
       
  
try:
    initapp()
    try:       
        main()
    except:       
        traceback.print_exc()
finally:
    endapp()

经测试每一次按键的时候屏幕的数据都刷新一次,经过尝试发现把cwin.clear()改成cwin.erase()就不会出现这种问题了。查看curses的API说明才发现自己犯了一个大错误:
clear( ) :
Like erase(), but also causes the whole window to be repainted upon next call to refresh().

   也就是说erase只会使子窗口刷新,而clear会导致整个窗口刷新。
看来还是自己太粗心了!

 

posted @ 2007-03-06 16:32 CowNew开源团队 阅读(326) | 评论 (0)编辑 收藏

 分页在任何系统中都是非常头疼的事情,有的数据库在语法上支持分页,而有的数据库则需要使用可滚动游标来实现,并且在不支持可滚动游标的系统上只能使用单向游标逐步接近要取得的数据。
 Hibernate提供了一个支持跨系统的分页机制,这样无论底层是什么样的数据库都能用统一的接口进行分页操作。比如下面的代码就是从第500条开始取出100条记录:
Query q = session.createQuery("from FooBar as f");
q.setFirstResult(500);
q.setMaxResults(100);
List l = q.list();
那么Hibernate底层如何实现分页的呢?Hibernate根据Query拼装SQL语句的地方是在org.hibernate.loader.Loader类的prepareQueryStatement方法中,对分页支持的代码在这一段中可以发现:
if (useLimit)
{
sql = dialect.getLimitString(
     sql.trim(), //use of trim() here is ugly?
     useOffset ? getFirstRow(selection) : 0,
     getMaxOrLimit(selection, dialect)
    );
 }
 此处调用Dialect的getLimitString方法来得到不同平台的分页语句。
在MySQLDialect中是如下实现getLimitString方法的:
public String getLimitString(String sql, boolean hasOffset)
{
return new StringBuffer( sql.length()+20 )
.append(sql)
.append( hasOffset ? " limit ?, ?" : " limit ?")
.toString();
}
 这是MySQL的专用分页语句,再来看Oracle9Dialect:
 public String getLimitString(String sql, boolean hasOffset) {
  
  sql = sql.trim();
  boolean isForUpdate = false;
  if ( sql.toLowerCase().endsWith(" for update") ) {
   sql = sql.substring( 0, sql.length()-11 );
   isForUpdate = true;
  }
  
  StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
  if (hasOffset) {
   pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
  }
  else {
   pagingSelect.append("select * from ( ");
  }
  pagingSelect.append(sql);
  if (hasOffset) {
   pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");
  }
  else {
   pagingSelect.append(" ) where rownum <= ?");
  }

  if ( isForUpdate ) {
   pagingSelect.append( " for update" );
  }
  
  return pagingSelect.toString();
 } 
Oracle采用嵌套3层的查询语句结合rownum来实现分页,这在Oracle上是最好的方式,因为如果只是一层或者两层的查询语句的rownum不能支持order by。
此外Interbase,PostgreSQL,HSQL等也在语法级别上支持分页,具体实现可以查看相应的Dialect实现。如果数据库不支持分页的SQL语句,那么如果数据库支持可滚动游标,那么Hibernate就会采使用ResultSet的absolute方法直接移到查询起点;否则使用循环语句,通过rs.next一步步移动到要查询的数据处:
final int firstRow = getFirstRow( selection );
if ( firstRow != 0 )
{
if ( getFactory().getSettings().isScrollableResultSetsEnabled() )
{
// we can go straight to the first required row
rs.absolute( firstRow );
}
else
{
// we need to step through the rows one row at a time (slow)
for ( int m = 0; m < firstRow; m++ ) rs.next();
}
}

可见使用Hibernate,在进行查询分页的操作上,是具有非常大的灵活性,Hibernate会首先尝试用特定数据库的分页sql,如果没用,再尝试Scrollable,如果不支持Scrollable再采用rset.next()移动的办法。这样既兼顾了查询分页的性能,同时又保证了代码在不同的数据库之间的可移植性。

posted @ 2007-03-06 09:22 CowNew开源团队 阅读(670) | 评论 (0)编辑 收藏

      当使用多个资源合作解决一个问题的时候,必须使这些资源在一个事务中进行合作。为了实现这一目的,将事务分为两个阶段进行:
      第一阶段开始时,向此事务涉及到的全部资源发送提交前信息。此时,事务涉及到的资源还有最后一次机会来回滚事务。如果任意一个资源决定回滚事务,那么整个事务将被取消。否则,事务会被提交。
第二阶段只是在第一阶段没有回滚时才会发生。在这个阶段,所有的能被定位和单独控制的资源都将真正的更新。
      事务被分割成两个阶段来完成,这被称为两阶段提交协议。如果程序在同一个操作中需要访问多种资源,您就要使用两阶段提交事务。例如,如果从 JMS 队列中删除一个消息,并且随后更新数据库中基于这条消息的纪录,这时,要保证这两个操作的原子性。不应该出现一条消息已经从队列中被删除,而系统没有更新与此消息相关的数据库中的纪录的情况。可以通过应用程序的代码在数据库更新失败的时候 "撤销"对队列的操作。但是这样做并不还,因为当程序在执行“撤销”操作的过程中服务器突然崩溃的话就会导致数据出现不一致。作为替代的方式,应该使用两阶段提交事务。
posted @ 2007-03-06 09:20 CowNew开源团队 阅读(356) | 评论 (0)编辑 收藏

out of the box:“The following apply to SCO 3 only; Python builds out of the box on SCO 5。”(源自:http://svn.python.org/projects/python/trunk/README
解释:
out-of-the-box具有“创造性的,独特性,思维不合常规”的意思,但在计算机术语里又可以指“从盒子里拿出来直接可以使用的,也就是即开即用”的意思。

因此上边那句的翻译是:下面所说的只适用于SCO3;在SCO 5中Python已经构建好了。

posted @ 2007-03-02 16:47 CowNew开源团队 阅读(283) | 评论 (0)编辑 收藏

仅列出标题
共30页: First 上一页 13 14 15 16 17 18 19 20 21 下一页 Last