??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美日韩免费看片,秋霞久久久久久一区二区,国产99久久久国产精品http://www.aygfsteel.com/joeyeezhang/zh-cnWed, 18 Jun 2025 06:05:00 GMTWed, 18 Jun 2025 06:05:00 GMT60又见在线divcss|页设计工具!http://www.aygfsteel.com/joeyeezhang/archive/2011/07/27/355099.htmljoeyeezhangjoeyeezhangWed, 27 Jul 2011 00:01:00 GMThttp://www.aygfsteel.com/joeyeezhang/archive/2011/07/27/355099.htmlhttp://www.aygfsteel.com/joeyeezhang/comments/355099.htmlhttp://www.aygfsteel.com/joeyeezhang/archive/2011/07/27/355099.html#Feedback0http://www.aygfsteel.com/joeyeezhang/comments/commentRss/355099.htmlhttp://www.aygfsteel.com/joeyeezhang/services/trackbacks/355099.html
q个|站提供了在U的|页~辑设计工具Q可视化的,很h性化Q功能很强大Q每个注册用户都?x)获得一个二U域名的|?站,q可以绑定一U域名ƈ 且不需要备案, 你可以在U的~辑你的|站文gQ也可以创徏|页文gQ还可以上传囄css和js文gQ也提供了css~辑和js~辑Q不q里面最好的q是|页~辑工具Q? ~辑完了C码视图copy出网代码,很方ѝ这个网站主要是做网站的Q不q我们程序员可以利用里面的编辑工兗?br />地址Q?a >http://imaiyi.com
试用地址Q?a >http://imaiyi.com/tryhtmleditor.htm
来几个截图:(x)













joeyeezhang 2011-07-27 08:01 发表评论
]]>
21U代码的“坏味道?/title><link>http://www.aygfsteel.com/joeyeezhang/archive/2007/01/16/94259.html</link><dc:creator>joeyeezhang</dc:creator><author>joeyeezhang</author><pubDate>Tue, 16 Jan 2007 09:48:00 GMT</pubDate><guid>http://www.aygfsteel.com/joeyeezhang/archive/2007/01/16/94259.html</guid><wfw:comment>http://www.aygfsteel.com/joeyeezhang/comments/94259.html</wfw:comment><comments>http://www.aygfsteel.com/joeyeezhang/archive/2007/01/16/94259.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/joeyeezhang/comments/commentRss/94259.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/joeyeezhang/services/trackbacks/94259.html</trackback:ping><description><![CDATA[<span id="ArticleContent1_ArticleContent1_lblContent">  <p>1QDuplicated Code<br />代码重复几乎是最常见的异味了。他也是Refactoring 的主要目标之一。代码重复往<br />往来自于copy-and-paste 的编E风根{与他相对应OAOO 是一个好pȝ的重要标?br />Q请参见我的duplicated code 一文:(x)<a >http://www.erptao.org/download.php?op=viewsdownload&sid=6</a>Q?/p><p><br />2QLong method<br />它是传统l构化的“遗毒“。一个方法应当具有自我独立的意图Q不要把几个意图<br />攑֜一P我的《大cd长方法》一文中有详l描q?/p><p><br />3QLarge Class<br />大类是你把太多的责Ml了一个类。这里的规则是One Class One Responsibility?/p><p>4QDivergent Change<br />一个类里面的内容变化率不同。某些状态一个小时变一ơ,某些则几个月一q才?br />一ơ;某些状态因斚w的原因发生变化,而另一些则因ؓ(f)其他斚w的原因变一ơ?br />面向对象的抽象就是把相对不变的和相对变化盔RR把问题变化的一斚w和另一<br />斚w盔RR这使得q些相对不变的可以重用。问题变化的每个斚w都可以单独重用?br />q种相异变化的共存得重用非常困难?/p><p><br />5QShotgun Surgery<br />q正好和上面相反。对pȝ一个地方的改变涉及(qing)到其他许多地方的相关改变。这?br />变化率和变化内容怼的状态和行ؓ(f)通常应当攑֜同一个类中?/p><p><br />6QFeature Envy<br />对象的目的就是封装状态以?qing)与q些状态紧密相关的行ؓ(f)。如果一个类的方法频J?br />用get Ҏ(gu)存取其他cȝ状态进行计,那么你要考虑把行为移到涉?qing)状态数目最多的<br />那个cR?/p><p><br />7QData Clumps<br />某些数据通常像孩子一h玩耍:(x)一起出现在很多cȝ成员变量中,一起出现在<br />许多Ҏ(gu)的参C…..Q这些数据或许应该自q立Ş成对象?/p><p><br />8QPrimitive Obsession<br />面向对象的新手通常?fn)惯使用几个原始cd的数据来表示一个概c(din)譬如对于范_(d)<br />他们?x)用两个数字。对于MoneyQ他们会(x)用一个QҎ(gu)来表C。因Z没有使用对象<br />来表N题中存在的概念,q得代码变的难以理解,解决问题的难度大大增加?br />好的?fn)惯是扩充语a所能提供原始类型,用小对象来表C围、金额、{化率、邮<br />政编码等{?/p><p><br />9QSwitch Statement<br />Z帔R的开兌句是OO 的大敌,你应当把他变为子cRstate 或strategy?/p><p><br />10Q?Parallel Inheritance Hierarchies<br />q行的承层ơ是shotgun surgery 的特D情c(din)因为当你改变一个层ơ中的某一?br />cLQ你必须同时改变另外一个层ơ的q行子类?/p><p><br />11Q?Lazy Class<br />一个干zM多的cR类的维护需要额外的开销Q如果一个类承担了太的责QQ应<br />当消除它?/p><p><br />12Q?Speculative Generality<br />一个类实现了从未用到的功能和通用性。通常q样的类或方法唯一的用htest<br />case。不要犹豫,删除它?/p><p><br />13Q?Temporary Field<br />一个对象的属性可能只在某些情况下才有意义。这L(fng)代码难以理解。专门徏?br />一个对象来持有q样的孤儿属性,把只和他相关的行为移到该cR最常见的是一个特?br />的算法需要某些只有该法才有用的变量?/p><p><br />14Q?Message Chain<br />消息铑֏生于当一个客户向一个对象要求另一个对象,然后客户又向q另一对象?br />求另一个对象,再向q另一个对象要求另一个对象,如此如此。这Ӟ你需要隐藏分z?/p><p><br />15Q?Middle Man<br />对象的基本特性之一是装Q而你l常?x)通过分派d现封装。但是这一步不能走得太q,如果你发C个类接口的一大半Ҏ(gu)都在做分z,你可能需要移去这个中?br />人?/p><p><br />16Q?Inappropriate Intimacy<br />某些cȝ互之间太亲密Q它们花费了太多的时间去砖研别h的私有部分。对人类?br />aQ我们也怸应该太假正经Q但我们应当让自qcM格遵守禁Ʋ主义?/p><p><br />17Q?Alternative Classes with Different Interfaces<br />做相同事情的Ҏ(gu)有不同的函数signatureQ一致把它们往cdơ上U,直至协议一<br />致?/p><p><br />18Q?Incomplete Library Class<br />要徏立一个好的类库非常困难。我们大量的E序工作都基于类库实现。然而,如此<br />q泛而又相异的目标对库构提Z苛刻的要求。库构徏者也不是万能的。有时候我<br />们会(x)发现库类无法实现我们需要的功能。而直接对库类的修Ҏ(gu)非常困难。这时候就需<br />要用各种手段q行Refactoring?/p><p><br />19Q?Data Class<br />对象包括状态和行ؓ(f)。如果一个类只有状态没有行为,那么肯定有什么地方出问题<br />了?/p><p><br />20Q?Refused Bequest<br />类传下来很多行为和状态,而子cd是用了其中的很小一部分。这通常意味着?br />的类层次有问题?/p><p><br />21Q?Comments<br />l常觉得要写很多注释表示你的代码难以理解。如果这U感觉太多,表示你需?br />Refactoring?/p></span> <a >卖艺|提?/a><img src ="http://www.aygfsteel.com/joeyeezhang/aggbug/94259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/joeyeezhang/" target="_blank">joeyeezhang</a> 2007-01-16 17:48 <a href="http://www.aygfsteel.com/joeyeezhang/archive/2007/01/16/94259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>极限~程(xp~程)ȝ http://www.aygfsteel.com/joeyeezhang/archive/2007/01/05/91894.htmljoeyeezhangjoeyeezhangFri, 05 Jan 2007 01:33:00 GMThttp://www.aygfsteel.com/joeyeezhang/archive/2007/01/05/91894.htmlhttp://www.aygfsteel.com/joeyeezhang/comments/91894.htmlhttp://www.aygfsteel.com/joeyeezhang/archive/2007/01/05/91894.html#Feedback0http://www.aygfsteel.com/joeyeezhang/comments/commentRss/91894.htmlhttp://www.aygfsteel.com/joeyeezhang/services/trackbacks/91894.html1.什么是xp~程(极限~程):

XP是勇气,交流Q反馈和单?br />XP是Y件开发过E中的纪律,它规定你Q必d~程前些试Q必M个h一L(fng)E,必须遵守~程规范……?br />XP是把最好的实践l验提取出来QŞ成了一个崭新的开发方法?/p>

2. XP适用范围:

极限~程Q也被叫做XPQ适用于中型团队在需求不明确或者迅速变化的情况下进行Y件开发的轻量U方法学?br />推荐使用范围?0人左右的团队

3.XP工作模式体现:

一、工作环?br />二、立式晨?br />三、结对编E?br />四、测试驱动开?br />五、重?br />六、持l集?br />七、频J地发布?yu)版?/p>

4.l对~程:

开发Q务会(x)l化分解为很多TaskQ一个Task的开发周期一般不过2天?br />每个Task的Owner?x)寻找一个Partnerq行l对开发?br />Task开发的ơ序q序员们自己协商。他可以先作为Partner和其他Owner一起开发某个TaskQ然后再扑֏一个程序员作ؓ(f)Partner来共同开发自己承担的Task?br />l对开发时QTask的Owner主要负责~码Q?Partner负责在一旁看Owner~程q在其编写有错误提出自己的意见,当其遇到困难时一赯论、互相帮助完成Q?/p>

5.试驱动开?

在动手编码之前,必须先写功能试脚本、单元测试脚本?br />写好试脚本后,开始编码、重构、运行单元测试、集成、运行功能测试,以此循环

6.重构:

减少重复设计Q优化设计结构,提高技术上的重用性和可扩展性?br />XP提倡毫不留情的重构?br />M人可以重构Q何代码,前提是重构后的代码一定要通过100%试单元试后才能被Check-in

7.持箋集成:

试先行是持l集成的一个重要前提?br />持箋集成指不断地把完成的功能模块整合在一赗目的在于不断获得客户反馈以?qing)尽早发现BUG?br />随时整合Q越频繁好Q集成及(qing)试q程的自动化E度高好?br />每次只有一个新增加部分在整合,而且必须q行功能试

8.频繁地发布小版本:

发布q程应该可能地自动化、规范化?br />不断地发布可用的pȝ可以告诉客户你在做正的事情?br />客户使用发布的系l,可以保证频繁地反馈和交流?br />保证客户有够的依据调控开发过E?增加、删除或改变需??br />降低开发风险?br />随着开发的推进Q发布越来越频繁?br />所有的发布都要l过功能试?/p>

9.XP的关键词:

试优先原则
l对~程
持箋集成
频繁版?br />不断重构
立式晨会(x)
交流和沟通,“只有没有沟通不够的目Q没有沟通过度的目”
分解d、制定计划是关键一?/p>

10.XP作用:

一、^E的工作效率

q稳的工作效率指团队和个人在很长的时期内保持一定的开发效率?br />保证了项目速度和计划过E的有效性和准确性;
保证了程序员可以持箋地完成Q务,团队可以持箋地向客户交付可运行的pȝQ?br />l对~程已经加大了工作强度,q且和其它XP的规则一h高了工作效率Qɞ加班和l持q稳的工作效率可能而且可行?br />提倡^E的工作效率Q体CXP以h为本的h(hun)D?br />二、高质量

试优先、ƈ坚持单元试、每个版本进行功能测试的原则是保证了高质量的一个关键;
充分的沟通交进一步减了写低质量代码的风险;
l对开发模式在互相学习(fn)中会(x)产出高质量的代码
三、Open

l对开发、每一处修攚w需要测试等{规则得实现集体拥有代码, “我们”的代码,而不?#8220;?#8221;的代码;
充分的沟通交可以将每个人的知识、思想׃nQ?br />让每个h都知道项目的设计、计划、进展情늭信息Q?br />大家都知道每个h都在做什么和怎么做;
四、对人的挑战
暴露自己的缺点,人的本?br />懒惰
自尊

……

克服自己的缺?br />高效?br />不怕告诉别׃?x),乐于问h
懂得重别hQ乐于帮助别?br />……

11.受益于XP:

一个曾l在XP模式下工作过的hQ回Cl开发模式下才深M?x)到XPl他带来的胦(ch)富?br />在传l开发模式下他坚持每天有计划、ȝQ坚持测试驱动开?#8230;…
发现他L按时下班甚至提前下班Q可是同事们来多且越来越晚下班,是自׃认真Q是同事们爱表现Q?#8230;…
都不是!Q?br />是XPl他带来的受益终w的开发方式,他的同事bug量远q比他多Q他只有不多的几?同事们Q务L延时Q而自己都是轻松按时完?#8230;…


卖艺|提?/a>

joeyeezhang 2007-01-05 09:33 发表评论
]]>
q代开发介l?/title><link>http://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91790.html</link><dc:creator>joeyeezhang</dc:creator><author>joeyeezhang</author><pubDate>Thu, 04 Jan 2007 08:49:00 GMT</pubDate><guid>http://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91790.html</guid><wfw:comment>http://www.aygfsteel.com/joeyeezhang/comments/91790.html</wfw:comment><comments>http://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/joeyeezhang/comments/commentRss/91790.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/joeyeezhang/services/trackbacks/91790.html</trackback:ping><description><![CDATA[<table style="table-layout: fixed;"> <tbody> <tr> <td> <div id="wmqeeuq" class="cnt">l你一个标准的定义Q?br />在RUP中,q代被定义ؓ(f)QP代包括生品发布(E_、可执行的品版本)的全部开发活动和要用该发布必需的所有其他外围元素?br /><br />q个定义太学I气Q半天看不明白。这栯释可能更Ҏ(gu)理解Q?br />我们开发一个品,如果不太复杂Q会(x)采用瀑布模型Q简单的说就是先需求定义,然后构徏框架Q然后写代码Q然后测试,最后发布一个品?br />q样Q几个月q去了,直到最后一天发布时Q大家才能见C个品?br /><br />q样的方式有明显的缺点,假如我们对用L(fng)需求判断的不是很准时——q是很常见的问题Q一点也不少?#8212;—你工作了几个月甚x几年Q当你把产品拿给客户看时Q客户往往?x)大吃一惊,q就是我要的东西吗?<br /><br />q代的方式就有所不同Q假如这个品要?个月交货Q我在第一个月׃(x)拿出一个品来Q当?dng)q个产品?x)很不完善,会(x)有很多功能q没有添加进去,bug很多Q还不稳定,但客L(fng)了以后,?x)提出更详细的修?gu)见,q样Q你q道自pdL(fng)需求有多远Q我回家以后Q再׃个月Q在上个月所作的需求分析、框架设计、代码、测试等{的基础上,q一步改q,又拿Z个更完善的品来Q给客户看,让他们提意见?br />pP我的产品在功能上、质量上都能够逐渐D客户的要求,不会(x)出现我花了大量心血后,直到最后发布之时才发现Ҏ(gu)不是客户要的东西?br /><br />q样的方法很不错Q但他也有自q~陷Q那是周期ѝ成本很高。在应付大项目、高风险目——比如是航天飞机的控制系l时QP代的成本比项目失败的风险成本低得多,用这U方式明显有优势?br />如果你是l自q单位开发一个小MISQ自׃比较清楚需求,工期上也不过׃个把月的旉Q用q代有Ҏ(gu)鸡用了牛刀Q那q是瀑布模型更管用,即是做得不对,多再花一个月重来Q没什么了不v<br /><a >卖艺|?/a></div> </td> </tr> </tbody> </table><img src ="http://www.aygfsteel.com/joeyeezhang/aggbug/91790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/joeyeezhang/" target="_blank">joeyeezhang</a> 2007-01-04 16:49 <a href="http://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>极限~程介绍http://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91782.htmljoeyeezhangjoeyeezhangThu, 04 Jan 2007 08:25:00 GMThttp://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91782.htmlhttp://www.aygfsteel.com/joeyeezhang/comments/91782.htmlhttp://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91782.html#Feedback0http://www.aygfsteel.com/joeyeezhang/comments/commentRss/91782.htmlhttp://www.aygfsteel.com/joeyeezhang/services/trackbacks/91782.htmlXP是一个轻量的、灵巧的软g开发方法;同时它也是一个非怸谨和周密的方法。它的基和h(hun)D是交、朴素、反馈和勇气Q即QQ何一个Y仉目都可以从四个方面入手进行改善:(x)加强交流Q从单做PL反馈Q勇于实事求是。XP是一U近螺旋式的开发方法,它将复杂的开发过E分解ؓ(f)一个个相对比较单的周期;通过U极的交、反馈以?qing)其它一pd的方法,开发h员和客户可以非常清楚开发进度、变化、待解决的问题和潜在的困隄QƈҎ(gu)实际情况?qing)时地调整开发过E?
什么是软g开?

软g开发的内容是:(x)需求、设计、编E和试Q?

需求:(x)不仅仅是用户需求,应该是开发中遇到的所有的需求。比如,你首先要知道做这个项目是Z解决什么问题;试案例中应该输入什么数?#8230;…Z清楚地知道这些需求,你经常要和客戗项目经理等交流?

设计Q编码前Q肯定有个计划告诉你要做什么,l构是怎样{等。你一定要按照q个来做Q否则可能会(x)一团糟?

~程Q如果在目截止日,你的E序不能跑v来或达不到客L(fng)要求Q你拿不到钱?

试Q目的是让你知道Q什么时候算是完成了。如果你聪明Q你应该先写测试,q样可以?qing)时知道你是否真地完成了。否则,你经怼(x)不知道,到底有哪些功能是真正完成了,预期目标还差多q?

软g开发中Q客户和开发h员都有自q基本权利和义务?
客户Q?
定义每个用户需求的商业优先U;
制订M计划Q包括用多少投资、经q多长时间、达C么目的;
在项目开发过E中的每个工作周Q都能让投资获得最大的收益Q?
通过重复q行你所指定的功能测试,准确地掌握项目进展情况;
能随时改变需求、功能或优先U,同时避免昂贵的再投资Q能够根据各U变化及(qing)时调整项目计划;
能够随时取消目Q项目取消时Q以前的开发工作不是一堆垃圾,已开发完的功能是合乎要求的,正在q行或未完成的的工作则应该是不难接手的?

开发h员:(x)
知道要做什么,以及(qing)要优先做什么;
工作有效率;
有问题或困难Ӟ能得到客戗同事、上U的回答或帮助;
对工作做评估QƈҎ(gu)周围情况的变化及(qing)旉新评伎ͼ
U极承担工作Q而不是消极接受分配;
一?0时工作Ӟ不加班?

q就是Y件开发,除此之外再还有其它要兛_的问题!


灵y的轻量软g开发方?

一套Y件开发方法是׃pd与开发相关的规则、规范和惯例。重量的开发方法严格定义了许多的规则、流E和相关的文工作。灵巧的轻量U开发方法,其规则和文档相对较少Q流E更加灵z,实施h相对较容易?

在Y件工E概念出C前,E序员们按照自己喜欢的方式开发Y件。程序的质量很难控制Q调试程序很J琐Q程序员之间也很难读懂对方写的代码?968q_(d)EdsgerDijkstralC(j)ACM写了一题为GOTOStatementConsideredHarmful的信QY件工E的概念由此诞生。程序员们开始摒弃以前的做法Q{而用更pȝ、更严格的开发方法。ؓ(f)了控制软g开发和控制其它产品生一样严|Z陆箋制定了很多规则和做法Q发明了很多软g工程Ҏ(gu)QY件质量开始得到大q度提高。随着遇到的问题更多,规则和流E也来精l和复杂?

C今天Q在实际开发过E中Q很多规则已l难于遵循,很多程复杂而难于理解,很多目中文的制作q程正在失去控制。h们试图提出更全面更好的一揽子Ҏ(gu)Q或者寄希望于更复杂的、功能更强大的辅助开发工PCaseToolsQ,但L不能成功Q而且开发规范和程变得来复杂和难以实施?

Z赶进度,E序员们l常跌一些指定的程Q很h能全面遵循那些重量开发方法?

p|的原因很单,q个世界没有万能药。因此,一些h提出Q将重量U开发方法中的规则和程q行删减、重整和优化Q这样就产生了很多适应不同需要的轻量U流E。在q些程中,合乎实际需要的规则被保留下来,不必要的复杂化开发的规被抛弃。而且Q和传统的开发方法相比,轻量U流E不再象水生U,而是更加灉|?

ExtremeProgrammingQXPQ就是这样一U灵巧的轻量UY件开发方法?


Z么称?#8220;Extreme”Q极限)

“Extreme”Q极限)是指Q对比传l的目开发方式,XP把它列出的每个方法和思想做到极限、做到最好;其它XP所不提倡的Q则一概忽略(如开发前期的整体设计{)。一个严格实施XP的项目,其开发过E应该是q稳的、高效的和快速的Q能够做C?0时工作制而不拖g目q度?

XP的Y件开发是什么样

1极限的工作环?

Z在Y件开发过E中最大程度地实现和满_户和开发h员的基本权利和义务,XP要求把工作环境也做得最好。每个参加项目开发的人都担M个角Ԍ目l理、项目监督h{等Qƈ履行相应的权利和义务。所有的人都在同一个开攄开发环境中工作Q最好是所有h在同一个大房子中工作,q有茶点供应Q每?0时Q不提倡加班;每天早晨Q所有h一L(fng)着开个短?x);墙上有一些大白板Q所有的Story卡、CRC卡等都脓(chung)在上面,讨论问题的时候可以在上面写写ȝQ下班后大家可以一L(fng)?sh)脑游?#8230;…?

2极限的需?

客户应该是项目开发队伍中的一员,而不是和开发h员分开的;因ؓ(f)从项目的计划到最后验Ӟ客户一直v着很重要的作用。开发h员和客户一P把各U需求变成一个个的需求模块(UserStoryQ,例如“计算q的Mh敎ͼ是把该q所有班的h数篏加?#8221;Q这些模块又?x)根据实际情况被l合在一h者被分解成更的模块Q它们都被记录在一些小卡片QStoryCardQ上Q之后分别被E序员们在各个小的周期开发中QIterationQ通常不超q?个星期)实现Q客h据每个模块的商业价值来指定它们的优先Q开发h员要做的是确定每个需求模块的开发风险,风险高的Q通常是因为缺乏类似的l验Q需求模块将被优先研I、探索和开发;l过开发h员和客户分别从不同的角度评估每个模块后,它们被安排在不同的开发周期里Q客户将得到一个尽可能准确的开发计划;客户为每个需求模块指定验收测试(功能试Q?

每发布一ơ开发的软gQ经q一个开发周期)Q用户都能得C个可以开始用的pȝQ这个系l全面实C相应的计划中的所有需求。而在一些传l的开发模式中Q无Z么功能,用户都要{到所有开发完成后才能开始用?

3极限的设?

从具体开发的角度来看QXP内层的过E是一个个Z试驱动的开发(TestDrivenDevelopmentQ周期,诸如计划和设计等外层的过E都是围l这些展开的。每个开发周期都有很多相应的单元试QUnitTestQ。刚开始,因ؓ(f)什么都没有实现Q所以所有的单元试都是p|的;随着一个个的需求模块的完成Q通过的单元测试也来多。通过q种方式Q客户和开发h员都很容易检验,是否履行了对客户的承诺。XP提倡对于简单的设计QSimpleDesignQ,是用最单的方式Q得ؓ(f)每个单的需求写出来的程序可以通过所有相关的单元试。XP抛弃那种一揽子详细设计方式QBigDesignUpFrontQ,因ؓ(f)q种设计中有很多内容是你现在或最q都Ҏ(gu)不需要的。XPq大力提倡设计复核(ReviewQ、代码复总?qing)重整和优化QRefectoryQ,所有的q些q程其实也是优化设计的过E;在这些过E中不断q行单元试和功能测试,可以保证l过重整和优化后的系l仍然符合所有需求?

4极限的编E?

既然~程很重要,XP提倡两个h一起写同一D늨序(PairProgrammingQ,而且代码所有权是归于整个开发队伍(CollectiveCodeOwnershipQ。程序员在写E序和重整优化程序的时候,都要严格遵守~程规范。Q何h都可以修改其他h写的E序Q修改后要确定新E序能通过单元试?

5极限的测?

既然试很重要,XP提倡在开始写E序之前先写单元试。开发h员应该经常把开发好的模块整合到一PContinuousIntegrationQ,每次整合后都要运行单元测试;做Q何的代码复核和修改,都要q行单元试Q发CBUGQ就要增加相应的试Q因此XPҎ(gu)不需要BUG数据库)。除了单元测试之外,q有整合试Q功能测试、负h试和pȝ试{。所有这些测试,是XP开发过E中最重要的文之一Q也是最l交付给用户的内容之一?


XP中的重要惯例和规?

1目开发小l(TeamQ?

在XP中,每个寚w目做贡献的h都应该是目开发小l中的一员。而且Q这个小l中必须臛_有一个h对用户需求非常清晎ͼ能够提出需求、决定各个需求的商业价|优先U)、根据需求等的变化调整项目计划等。这个h扮演的是“客户”q个角色Q当然最好就是实际的最l用P因ؓ(f)整个目是围绕最l用L(fng)需求而展开的。程序员是项目开发小l中必不可少的成员。小l中可以有测试员Q他们帮助客户制订验收测试;有分析员Q帮助客L(fng)定需求;通常q有个CoachQ教l)Q负责跟t开发进度、解军_发中遇到的一些问题、推动项目进行;q可以又一个项目经理,负责调配资源、协助项目内外的交流沟通等{。项目小l中有这么多角色Q但q不是说Q每个h做的工作是别Z能插手或q预的,XP鼓励每个人尽可能Cؓ(f)目多做贡献。^{相处,取长补短Q这是最好的XP开发小l?

2计划目QPlanningGameQ、验收测试、小规模发布QSmallReleasesQ?

XP开发小l用简单的方式q行目计划和开发跟t,q以ơ预项目进展情况和军_未来的步骤。根据需求的商业价|开发小l针对一l组的需求进行一pd的开发和整合Q每ơ开发都?x)生一个通过试的、可以用的pȝ?

计划目

XP的计划过E主要针对Y件开发中的两个问题:(x)预测在交付日期前可以完成多少工作Q现在和下一步该做些什么。不断的回答q两个问题,是直接服务于如何实施及(qing)调整开发过E;与此相比Q希望一开始就_定义整个开发过E要做什么事情以?qing)每件事情要花多时_(d)则事倍功半。针对这两个问题QXP中又两个主要的相应过E:(x)

软g发布计划QReleasePlanningQ。客户阐q需求,开发h员估开发成本和风险。客h据开发成本、风险和每个需求的重要性,制订一个大致的目计划。最初的目计划没有必要Q也没有可能Q非常准,因ؓ(f)每个需求的开发成本、风险及(qing)光要性都不是一成不变的。而且Q这个计划会(x)在实施过E中被不断地调整以趋_?

周期开发计划(IterationPlanningQ。开发过E中Q应该有很多阶段计划Q比如每三个星期一个计划)。开发h员可能在某个周期对系l进行内部的重整和优化(代码和设计)Q而在某个周期增加了新功能Q或者会(x)在一个周期内同时做两斚w的工作。但是,l过每个开发周期,用户都应该能得到一个已l实C一些功能的pȝ。而且Q每l过一个周期,客户׃(x)再提出确定下一个周期要完成的需求。在每个开发周期中Q开发h员会(x)把需求分解成一个个很小的Q务,然后估计每个d的开发成本和风险。这些估是Z实际开发经验的Q项目做得多了,估算自然更加准确和精;在同一个项目中Q每l过一个开发周期,下一ơ的估算都会(x)有更q的l验、参照和依据Q从而更加准。这些简单的步骤对客h供了丰富的、够的信息Q之能灉|有效地调控开发进E。每q两三个星期Q客h能够实实在在地看到开发h员已l完成的需求。在XP里,没有什?#8220;快要完成?#8221;?#8220;完成?0%”的模p说法,要不是完成了Q要不就是没完成。这U做法看h好象有利有弊Q好处是客户可以马上知道完成了哪些、做出来的东西是否合用、下面还要做些什么或改进什么等{;坏处是客L(fng)到做出来的东西,可能?x)很不满意甚至中止合同。实际上QXP的这U做法是Z?qing)早发现问题、解决问题,而不是等到过了几个月Q用L(fng)于看到开发完的系l了Q然后才告诉你这个不行、那个变了、还要增?
哪个内容{等?

验收试

客户Ҏ(gu)个需求都定义了一些验收测试。通过q行验收试Q开发h员和客户可以知道开发出来的软g是否W合要求。XP开发h员把q些验收试看得和单元测试一样重要。ؓ(f)了不费宝贵的时_(d)最好能这些测试过E自动化?

频繁地小规模发布软gQSmallReleasesQ?

每个周期QIterationQ开发的需求都是用h需要的东西。在XP中,对于每个周期完成时发布的pȝQ用户都应该可以很容易地q行评估Q或者已l能够投入实际用。这P软g开发对于客h_(d)不再是看不见怸着的东西,而是实实在在的。XP要求频繁地发布YӞ如果有可能,应该每天都发布一个新版本Q而且在完成Q何一个改动、整合或者新需求后Q就应该立即发布一个新版本。这些版本的一致性和可靠性,是靠验收试和测试驱动的开发来保证的?

3单设计,PairProgrammingQ测试驱动开发,重整和优?

XPE序员不但做Z个开发小l共同工作,q以两个Zؓ(f)一个小开发单元编写同一个程序。开发h员们q行单的设计Q编写单元测试后再编写符合测试要求的代码Qƈ在满需求的前提下不断地优化设计?

单设?

XP中让初学者感到最困惑的就是这炏VXP要求用最单的办法实现每个需求,前提是按照这些简单设计开发出来的软g必须通过试。这些设计只要能满pȝ和客户在当下的需求就可以了,不需要Q何画蛇添的设计Q而且所有这些设计都在后箋的开发过E中p不断地重整和优化?

在XP中,没有那种传统开发模式中一ơ性的、针Ҏ(gu)有需求的M设计。在XP中,设计q程几乎一直诏I着整个目开发:(x)从制订项目的计划Q到制订每个开发周期(IterationQ的计划Q到针对每个需求模块的捯计,到设计的复核Q以?qing)一直不间断的设计重整和优化。整个设计过E是个螺旋式的、不断前q和发展的过E。从q个角度看,XP是把设计做到了极致?

PairProgramming

XP中,所有的代码都是׃个程序员在同一台机器上一起写?#8212;—q是XP中让Z议最多、也是最隑֮施的一炏V这保证了所有的代码、设计和单元试臛_被另一个h复核q,代码、设计和试的质量因此得到提高。看hq样象是在浪费h力资源,但是各种研究表明事实恰恰相反?#8212;—q种工作方式极大地提高了工作强度和工作效率?

很多E序员一开始是被迫试q点的(XP也需要行政命令的支持Q。开始时L不习(fn)惯的Q而且两个人的效率不会(x)比一个h的效率高。这U做法的效果往往要坚持几个星期或一两个月后才能很显著。据l计Q在所有刚开始PairProgramming的程序员中,90%的h在两个月以后都很认ؓ(f)q种工作方式更加高效?

目开发中Q每个h?x)不断地更换合作~程的伙伴。因此,PairProgramming不但提高了Y件质量,q增Z怺之间的知识交和更新Q增Z怺之间的沟通和理解。这不但有利于个人,也有利于整个目、开发队伍和公司。从q点看,PairProgramming不仅仅适用于XPQ也适用于所有其它的软g开发方法?

试驱动开?

反馈是XP的四个基本的价D之一——在Y件开发中Q只有通过充分的测试才能获得充分的反馈。XP中提出的试Q在其它软g开发方法中都可以见刎ͼ比如功能试、单元测试、系l测试和负荷试{;与众不同的是QXP测试结合到它独特的螺旋式增量型开发过E中Q测试随着目的进展而不断积累。另外,׃整个开发小l拥有代码,试也是由大家共同维护的。即QQ何h在往代码库中攄序(CheckInQ前Q都应该q行一遍所有的试QQ何h如果发现了一个BUGQ都应该立即个BUG增加一个测试,而不是等待写那个E序的h来完成;M人接手其他h的Q务,或者修改其他h的代码和设计Q改动完以后如果能通过所有测试,p明他的工作没有破坏愿pȝ。这P试才能真正起到帮助获得反馈的作用;而且Q通过不断C先编写和累积Q测试应该可以基本覆盖全部的客户和开发需求,因此开发h员和客户可以得到可能充的反馈?

重整和优?Refactoring)

XP单的设计Q但单的设计q不是没有设计的水帐式的程序,也不是没有结构、缺乏重用性的E序设计。开发h员虽然对每个USERSTORY都进行简单设计,但同时也在不断地对设计进行改q,q个q程叫设计的重整和优化(RefactoringQ。这个名字最早出现在MartinFowler写的《Refactoring:ImprovingtheDesignofExistingCode》这本书中?

Refactoring主要是努力减程序和设计中重复出现的部分Q增强程序和设计的可重用性。Refactoring的概念ƈ不是XP首创的,它已l被提出了近30q了Q而且一直被认ؓ(f)是高质量的代码的特点之一。但XPQ把Refactoring做到极致Q应该随旉地、尽可能地进行RefactoringQ只要有可能Q程序员都不应该心疼以前写的E序Q而要毫不留情地改q程序。当?dng)每次改动后,E序员都应该q行试E序Q保证新pȝ仍然W合预定的要求?

4频繁地整合,集体拥有代码QCollectiveCodeOwnershipQ,~程规范

XP开发小l经常整合不同的模块。ؓ(f)了提高Y件质量,除了试驱动开发和PairProgramming以外QXP要求每个人的代码都要遵守~程规范QQ何h都可以修改其他h写的代码Q而且所有h都应该主动检查其他h写的代码?

频繁地整合(IntegrationQ?

在很多项目中Q开发h员往往很迟才把各个模块整合在一赗在q些目中,开发h员经常在整合q程中发现很多问题,但不能肯定到底是谁的E序Z问题Q而且Q只有整合完成后Q开发h员才开始稍E用整个系l,然后马上交付给客户验收。对于客h_(d)即ɘq些pȝ能够通过l验收测试,因ؓ(f)使用旉短,客户门心里ƈ没有多少把握?

Z解决q些问题QXP提出Q整个项目过E中Q应该频J地Q尽可能地整合已l开发完的USERSTORYQ每ơ整合一个新的USERSTORYQ。每ơ整合,都要q行相应的单元测试和验收试Q保证符合客户和开发的要求。整合后Q就发布一个新的应用系l。这P整个目开发过E中Q几乎每隔一两天Q都?x)发布一个新pȝQ有时甚至会(x)一天发布好几个版本。通过q个q程Q客戯非常清楚地掌握已l完成的功能和开发进度,q基于这些情况和开发h员进行有效地、及(qing)时地交流Q以保目利完成?

集体拥有代码QCollectiveCodeOwnershipQ?

在很多项目开发过E中Q开发h员只l护自己的代码,而且很多Z喜欢其他人随意修改自q代码。因此,即可能有相应的比较详细的开发文,但一个程序员却很、也不太愿意去读其他E序员的代码Q而且Q因Z清楚其他人的E序到底实现了什么功能,一个程序员一般也不敢随便改动其他人的代码。同Ӟ因ؓ(f)是自q护自q代码Q可能因为时间紧张或技术水q的局限性,某些问题一直不能被发现或得到比较好的解冟뀂针对这点,XP提倡大家共同拥有代码,每个人都有权利和义务阅读其他代码Q发现和U正错误Q重整和优化代码。这Pq些代码׃仅仅是一两个人写的,而是由整个项目开发队伍共同完成的Q错误会(x)减少很多Q重用性会(x)可能地得到提高Q代码质量是非常好?

Z防止修改其他人的代码而引L(fng)l崩溃,每个人在修改后都应该q行试E序。(从这点,我们可以再次看到QXP的各个惯例和规则是怎样有机地结合在一L(fng)。)

~程规范

XP开发小l中的所有h都遵循一个统一的编E标准,因此Q所有的代码看v来好像是一个h写的。因为有了统一的编E规范,每个E序员更加容易读懂其他h写的代码Q这是是实现CollectiveCodeOwnership的重要前提之一?

5MetaphorQ系l比喻)Q不加班

XPq程通过使用一些Ş象的比喻让所有h对系l有个共同的、简z的认识。XP认ؓ(f)加班是不正常的,因ؓ(f)q说明关于项目进度的估计和安排有问题?

MetaphorQ系l比喻)

Z帮助每个Z致清楚地理解要完成的客户需求、要开发的pȝ功能QXP开发小l用很多形象的比L描述pȝ或功能模块是怎样工作的。比如,对于一个搜索引擎,它的Metaphor可能是“一大群蜘蛛Q在|上四处L要捕捉的东西Q然后把东西带回巢穴?#8221;

不加?

大量的加班意味着原来的计划是不准的Q或者是E序q不清楚自己到底什么时候能完成什么工作。而且Q开发管理h员和客户也因此无法准掌握开发速度Q开发h员也因此非常疲劳。XP认ؓ(f)Q如果出现大量的加班现象Q开发管理h员(比如CoachQ应该和客户一L(fng)定加班的原因Qƈ?qing)时调整目计划、进度和资源?


XP中一些基本概늚?

UserStoryQ开发h员要求客h所有的需求写成一个个独立的小故事Q每个只需要几天时间就可以完成。开发过E中Q客户可以随时提出新的UserStoryQ或者更改以前的UserStory?

StoryEstimates和开发速度Q开发小l对每个UserStoryq行估算QƈҎ(gu)每个开发周期(IterationQ中的实际情况反复计开发速度。这P开发h员和客户能知道每个星期到底能开发多UserStory?

ReleasePlan和ReleaseScopeQ整个开发过E中Q开发h员将不断地发布新版本。开发h员和客户一L(fng)定每个发布所包含的UserStory?

IterationQ开发周期)和IterationPlanQ在一个Releaseq程中,开发h员要求客户选择最有h(hun)值的UserStory作ؓ(f)未来一两个星期的开发内宏V?

TheSeedQ第一个开发周期(IterationQ完成后Q提交给客户的系l。虽然这不是最l的产品Q但它已l实C几个客户认ؓ(f)是最重要的StoryQ开发h员将逐步在其基础上增加新的模块?

ContinuousIntegrationQ整合)Q把开发完的UserStory的模块一个个DhQ一步步接近乃至最l完成最l品?

验收试Q功能测试)Q对于每个UserStoryQ客户将定义一些测试案例,开发h员将使运行这些测试案例的q程自动化?

UnitTestQ单元测试)Q在开始写E序前,E序员针对大部分cȝҎ(gu)Q先写出相应的测试程序?

Refactoring(重整和优?Q去掉代码中的冗余部分,增加代码的可重用性和伸羃性?




XP的一个成功因素是重视客户的反?#8212;—开发的目的是Z满客户的需要。XPҎ(gu)使开发h员始l都能自信地面对客户需求的变化。XP团队合作Q经理、客户和开发h员都是开发团队中的一员。团队通过怺之间的充分交和合作Q用XPq种单但有效的方式,努力开发出高质量的软g。XP的设计简单而高效;E序员们通过试获得客户反馈QƈҎ(gu)变化修改代码和设计,他们L争取可能早地将软g交付l客戗XPE序员能够勇于面寚w求和技术上的变化?

XP很象一个由很多块Dv来的智力拼图Q单独看每一块都没有什么意义,但拼装好后,一q美丽的囄׃(x)呈现在你面前?br />卖艺|?/a>

joeyeezhang 2007-01-04 16:25 发表评论
]]>
软gq程QTSPQRUP和XPhttp://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91721.htmljoeyeezhangjoeyeezhangThu, 04 Jan 2007 03:54:00 GMThttp://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91721.htmlhttp://www.aygfsteel.com/joeyeezhang/comments/91721.htmlhttp://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91721.html#Feedback0http://www.aygfsteel.com/joeyeezhang/comments/commentRss/91721.htmlhttp://www.aygfsteel.com/joeyeezhang/services/trackbacks/91721.html说到Z么我喜欢在实验室推广XPQ我们先来看看几个Y件过E?

  首先是RUPQRUP有什么特点呢QP代性开发,用例驱动Q用UML对Y件徏模,提倡事先设计好以组件ؓ(f)核心的体pȝ?以体pȝ构ؓ(f)中心)Q不断的评估和测试Y件质量,Q用用例)控制软g的变化。在q些原则的基上,把Y件h员分成各U角?分析Q开发,理Q测试,工具支持Q配|?{等Q在软g开发过E中的各U品叫做工?Artifact)?/p>

  再看TSPQTSP把h员分成小l领D、开发经理、计划经理、质量/生l理Q以?qing)技术支持经?注意q点和RUP的雷同),要求各个人员严格记录在Y件开发过E中的每一步,比如E序的Bug率,使用的时间等{?/p>

  最后一个是XPQXP的特点,双h~程Q简单用?User Story)QRefactoringQ以周ؓ(f)基础的P代。持l集成,现场客户Q测试驱动,自动化测试,代码同步。同L(fng)QXP也把人员分成试Q交h员,设计师,技术作者,客户Q程序员{等?/p>

  OKQ说了这么多长篇大论Q是Z把几个Y件过E拿出来比较。所有的软gq程无非是ؓ(f)了避免风险,保证目的成功?/p>

  拿交通工具做比方的话QTSP好比坐火RQ由于TSP是CMM那帮子h搞的Q所以TSP不强调P代性开发。TSP的是质量理和控Ӟ通过每个觉自愿的记录每天的行为,从而的得到严格的项目的数据Q缺乏了q种严格控制QTSP好比火车没有轨道,一点用处也没有。而在我们实验室一帮懒懒散散的学生中搞数据Q要他们每天填表Q从而知道项目消耗了多少人时QBug率ؓ(f)多少Q不要做梦了吧,所以TSP那套方式肯定是行不通的?/p>

  再看XP和RUP的差别,q代性开发,两者都Q不q两者的含义不同Q在RUP中,每次q代Q强调生的是一个个工gQ比如完成了用例。而在XP中,产生的是可用的Y件。ؓ(f)什么RUP的P代里面可能没有生可用的软g呢?因ؓ(f)RUP的是用例驱动和体pȝ构ؓ(f)中心Q所以RUP花在设计体系l构和用例上的时间会(x)比较多,q样带来的好处是软g的后期变更会(x)比较?yu)。而XP本n的是拥抱变化Q不三七二十一Q先开发出来一个能用的再说Q如果客户不满意Q别忘了QXP是现场客PQRefactoring之。所以在XP的开头的时候,Ҏ(gu)׃提倡太复杂的用例(客户在现场嘛Q不懂客L(fng)意思,现场交流啊)Q也不提倡过多的设计Q测试驱动嘛Q通不q的话Refactoring之)?/p>

  然而RUP没有现场客户的概念,所以清晰的用例描述是RUP中很重要的一环。只有这些用例在客户和团队之间达成了pQ才能做下一步的工作Q同L(fng)Q需求的变更也必通过用例来体玎ͼRUP很强调变更管理,是q个意思?/p>

  而在我们实验室做现在q个目Q不是和客户交流的问题,而是没有客户Q!Q?/p>

  所以,在这U程度下Q我们的用例Q不是要让客L(fng)解,而是我们自己理解p够了。而体pȝ构,׃你们现在不用考虑分布式,q发Q事务等{一pd东西。这些东襉K由J2EE做了?br />
  此外RUP在我们实验室很难办的一件事情是对各个阶D生的工g的质量监控,同学们互相哈哈哈Q很隑֯一个文性的东西q行评h(hun)?br />
     那么要改善我们现在做的项目,最重要的是做什么呢Q第一是,P代,我们现在整个软g开发周期太长了Q应该羃短到2Q?周以内。第二,试Q我们现在的试很多都是手动的,需要自动化q个试q程。第三是Q快速构建,持箋集成。整个Y件的部v周期不能像现在这么长Q不能由同学们手工构建,而必L自动化的部v。这些都是在XP中强调的?br />
     RUP的不同就好比是做BUS和自己开汽车的不同Q尽细微,但是Q开汽车更需要小心翼的调整方向Q而公交R毕竟有线路?br />   
  如果在一个大公司做部门经理的话,我更愿意采用RUP那套方式Q辅之于XP的各U实践,然而在实验室,我只有退而求其次Q因地制宜,XP能推q多是多少Q一些很难推q的东西比如风险理QBUG理只能暂时攑ּ了?/p>

爱卖?/a>



joeyeezhang 2007-01-04 11:54 发表评论
]]>
软g目l理的基本职?/title><link>http://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91713.html</link><dc:creator>joeyeezhang</dc:creator><author>joeyeezhang</author><pubDate>Thu, 04 Jan 2007 03:15:00 GMT</pubDate><guid>http://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91713.html</guid><wfw:comment>http://www.aygfsteel.com/joeyeezhang/comments/91713.html</wfw:comment><comments>http://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91713.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/joeyeezhang/comments/commentRss/91713.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/joeyeezhang/services/trackbacks/91713.html</trackback:ping><description><![CDATA[<span id="wmqeeuq" class="javascript" id="text166232" style="font-size: 12px;"> <font face="Verdana">软g目l理的基本职? <br /><br />1. 制定目计划QƈҎ(gu)各种变化修改目计划 <br />2. 实施 目的管理、开发、质量保?q程Q确保客L(fng)成本、进度、W效和质量目标.<br />3. 制定有效的项目决{过E?br />4. 保在项目生命周期中遵@是实施公司的理和质量政{?br />5. 选择一个能够精衡量项目成本、进度、质量、W效的目距阵<br />6. 风险理<br />7. 招聘和培训必ȝ目成员 <br />8. 定目的h员组l结? <br />9. 定期举行目评估(review)?x)?<br />10.为项目所有成员提供够的讑֤、有效的工具和项目开发过E?<br />11.有效理目资源<br /><a >爱卖?/a><br /></font> </span><img src ="http://www.aygfsteel.com/joeyeezhang/aggbug/91713.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/joeyeezhang/" target="_blank">joeyeezhang</a> 2007-01-04 11:15 <a href="http://www.aygfsteel.com/joeyeezhang/archive/2007/01/04/91713.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaU程ȝ http://www.aygfsteel.com/joeyeezhang/archive/2006/12/26/90183.htmljoeyeezhangjoeyeezhangTue, 26 Dec 2006 14:45:00 GMThttp://www.aygfsteel.com/joeyeezhang/archive/2006/12/26/90183.htmlhttp://www.aygfsteel.com/joeyeezhang/comments/90183.htmlhttp://www.aygfsteel.com/joeyeezhang/archive/2006/12/26/90183.html#Feedback0http://www.aygfsteel.com/joeyeezhang/comments/commentRss/90183.htmlhttp://www.aygfsteel.com/joeyeezhang/services/trackbacks/90183.html首先要理解线E首先需要了解一些基本的东西Q我们现在所使用的大多数操作pȝ都属于多dQ分时操作系l。正是由于这U操作系l的出现才有了多U程q个概念。我们用的windows,linux属于此列。什么是分时操作pȝ呢,通俗一点与是可以同一旉执行多个E序的操作系l,在自q?sh)脑上面Q你是不是一边听歌,一边聊天还一边看|页呢?但实际上Qƈ不上cpu在同时执行这些程序,cpu只是时间切割ؓ(f)旉片,然后时间片分配l这些程序,获得旉片的E序开始执行,不等执行完毕Q下个程序又获得旉片开始执行,q样多个E序轮流执行一D|_(d)׃现在cpu的高速计能力,lh的感觉就像是多个E序在同时执行一栗?br />一般可以在同一旉内执行多个程序的操作pȝ都有q程的概?一个进E就是一个执行中的程?而每一个进E都有自q立的一块内存空?一l系l资?在进E概念中,每一个进E的内部数据和状态都是完全独立的.因此可以惛_创徏q执行一个进E的pȝ开像是比较大的Q所以线E出C。在java中,E序通过控制来执行E序?E序中单个顺序的控制称为线E?多线E则指的是在单个E序中可以同时运行多个不同的U程,执行不同的Q?多线E意味着一个程序的多行语句可以看上d乎在同一旉内同时运?Q你可以前面一句话的程序换成进E,q程是程序的一ơ执行过E?是系l运行程序的基本单位Q?br />
U程与进E相?是一D完成某个特定功能的代码,是程序中单个序的流控制;但与q程不同的是,同类的多个线E是׃n一块内存空间和一l系l资?而线E本w的数据通常只有微处理器的寄存器数据,以及(qing)一个供E序执行时用的堆栈.所以系l在产生一个线E?或者在各个U程之间切换?负担要比q程的?正因如此,U程也被UCؓ(f)轻负药E?light-weight process).一个进E中可以包含多个U程.

多Q务是指在一个系l中可以同时q行多个E序,x多个独立q行的Q?每个d对应一个进E,同进E一?一个线E也有从创徏,q行到消亡的q程,UCؓ(f)U程的生命周?用线E的状?state)表明U程处在生命周期的哪个阶D?U程有创?可运?q行?d,M五中状?通过U程的控制与调度可ɾU程在这几种状态间转化每个E序臛_自动拥有一个线E?UCؓ(f)ȝE?当程序加载到内存?启动ȝE?

[U程的运行机制以?qing)调度模型]
java中多U程是一个类或一个程序执行或理多个U程执行d的能力,每个U程可以独立于其他线E而独立运行,当然也可以和其他U程协同q行Q一个类控制着它的所有线E,可以军_哪个U程得到优先U,哪个U程可以讉K其他cȝ资源Q哪个线E开始执行,哪个保持休眠状态?br />下面是线E的机制图:(x)
image

U程的状态表C线E正在进行的zd以及(qing)在此旉D内所能完成的d.U程有创?可运?q行?d,M五中状?一个具有生命的U程,L处于q五U状态之一Q?br />1.创徏状?/strong>
使用newq算W创Z个线E后,该线E仅仅是一个空对象,pȝ没有分配资源,U该U程处于创徏状?new thread)
2.可运行状?/strong>
使用start()Ҏ(gu)启动一个线E后,pȝU程分配了除CPU外的所需资源,使该U程处于可运行状?Runnable)
3.q行中状?/strong>
Javaq行pȝ通过调度选中一个Runnable的线E?使其占有CPUq{行中状?Running).此时,pȝ真正执行U程的run()Ҏ(gu).
4.d状?/strong>
一个正在运行的U程因某U原因不能l运行时,q入d状?Blocked)
5.M状?/strong>
U程l束后是M状?Dead)

同一时刻如果有多个线E处于可q行状?则他们需要排队等待CPU资源.此时每个U程自动获得一个线E的优先U?priority),优先U的高低反映U程的重要或紧急程?可运行状态的U程按优先排队,U程调度依据优先U基上的"先到先服?原则.
U程调度理器负责线E排队和CPU在线E间的分?q由U程调度法q行调度.当线E调度管理器选种某个U程?该线E获得CPU资源而进入运行状?

U程调度是先占式调度,卛_果在当前U程执行q程中一个更高优先的线E进入可q行状?则这个线E立卌调度执行.先占式调度分?独占式和分时方式.
独占方式?当前执行U程一直执行下??到执行完毕或׃某种原因d攑ּCPU,或CPU被一个更高优先的线E抢?br />分时方式?当前q行U程获得一个时间片,旉到时,即没有执行完也要让出CPU,q入可运行状?{待下一个时间片的调?pȝ选中其他可运行状态的U程执行
分时方式的系l每个U程工作若干?实现多线E同时运?br />
另外h意下面的U程调度规则Q如果有不理解,不急,往下看Q:(x)
①如果两个或是两个以上的U程都修改一个对象,那么把执行修改的Ҏ(gu)定义同步的(SynchronizedQ?如果对象更新影响到只L法,那么只度Ҏ(gu)也应该定义ؓ(f)同步?br />②如果一个线E必ȝ待一个对象状态发生变化,那么它应该在对象内部{待Q而不是在外部{待Q它可以调用一个被同步的方法,q让q个Ҏ(gu)调用wait()
③每当一个方法改变某个对象的状态的时候,它应该调用notifyAll()Ҏ(gu)Q这l等待队列的U程提供Z(x)来看一看执行环境是否已发生改变
④记住wait(),notify(),notifyAll()Ҏ(gu)属于Objectc,而不是Threadc,仔细(g)查看是否每次执行wait()Ҏ(gu)都有相应的notify()或notifyAll()Ҏ(gu)Q且它们作用与相同的对象 在java中每个类都有一个主U程Q要执行一个程序,那么q个cd中一定要有mainҎ(gu)Q这个manҎ(gu)也就是java class中的ȝE。你可以自己创徏U程Q有两种Ҏ(gu)Q一是承Threadc,或是实现Runnable接口。一般情况下Q最好避免承,因ؓ(f)java中是单根l承Q如果你选用l承Q那么你的类失MҎ(gu),当然也不能全然否定承Thread,该方法编写简?可以直接操作U程,适用于单重承情c(din)至于选用那一U,具体情况具体分析?br />

eg.l承Thread

public class MyThread_1 extends Thread
{
public void run()
{
//some code
}
}



eg.实现Runnable接口

public class MyThread_2 implements Runnable
{
public void run()
{
//some code
}
}




当用承创建线E,q样启动U程Q?br />

new MyThread_1().start()



当用实现接口创建线E,q样启动U程Q?br />

new Thread(new MyThread_2()).start()



注意Q其实是创徏一个线E实例,q以实现了Runnable接口的类为参C入这个实例,当执行这个线E的时候,MyThread_2中run里面的代码将被执行?br />下面是完成的例子Q?br />

public class MyThread implements Runnable
{

public void run()
{
System.out.println("My Name is "+Thread.currentThread().getName());
}
public static void main(String[] args)
{
new Thread(new MyThread()).start();
}
}




执行后将打印出:(x)
My Name is Thread-0

你也可以创徏多个U程Q像下面q样

new Thread(new MyThread()).start();
new Thread(new MyThread()).start();
new Thread(new MyThread()).start();




那么?x)打印出Q?br />My Name is Thread-0
My Name is Thread-1
My Name is Thread-2


看了上面的结果,你可能会(x)认ؓ(f)U程的执行顺序是依次执行的,但是那只是一般情况,千万不要用以为是U程的执行机Ӟ影响U程执行序的因素有几点Q首先看看前面提到的优先U别


public class MyThread implements Runnable
{

public void run()
{
System.out.println("My Name is "+Thread.currentThread().getName());
}
public static void main(String[] args)
{
Thread t1=new Thread(new MyThread());
Thread t2=new Thread(new MyThread());
Thread t3=new Thread(new MyThread());
t2.setPriority(Thread.MAX_PRIORITY);//赋予最高优先
t1.start();
t2.start();
t3.start();
}
}



再看看结果:(x)
My Name is Thread-1
My Name is Thread-0
My Name is Thread-2



U程的优先分ؓ(f)10U,分别??0的整C表,默认情况?。上面的t2.setPriority(Thread.MAX_PRIORITY){h(hun)与t2.setPriority(10Q?br />然后是线E程序本w的设计Q比如用sleep,yield,joinQwait{方法(详情L(fng)JDKDocument)

public class MyThread implements Runnable
{
public void run()
{
try
{
int sleepTime=(int)(Math.random()*100);//产生随机数字Q?br />Thread.currentThread().sleep(sleepTime);//让其休眠一定时_(d)旉又上面sleepTime军_
//public static void sleep(long millis)throw InterruptedException QAPIQ?br />System.out.println(Thread.currentThread().getName()+" 睡了 "+sleepTime);
}catch(InterruptedException ie)//׃U程在休眠可能被中断Q所以调用sleepҎ(gu)的时候需要捕捉异?br />{
ie.printStackTrace();
}
}
public static void main(String[] args)
{
Thread t1=new Thread(new MyThread());
Thread t2=new Thread(new MyThread());
Thread t3=new Thread(new MyThread());
t1.start();
t2.start();
t3.start();
}
}



执行后观察其输出Q?br />
Thread-0 睡了 11
Thread-2 睡了 48
Thread-1 睡了 69




上面的执行结果是随机的,再执行很可能出现不同的结果。由于上面我在run中添加了休眠语句Q当U程休眠的时候就?x)让出cpuQcpu会(x)选择执行处于runnable状态中的其他线E,当然也可能出现这U情况,休眠的Thread立即q入了runnable状态,cpu再次执行它?br />[U程l概念]
U程是可以被l织的,java中存在线E组的概念,每个U程都是一个线E组的成?U程l把多个U程集成Z个对?通过U程l可以同时对其中的多个线E进行操?如启动一个线E组的所有线E等.Java的线E组由java.lang包中的Thread——Groupcd?
ThreadGroupcȝ来管理一l线E?包括:U程的数?U程间的关系,U程正在执行的操?以及(qing)U程要启动或终止时间等.U程l还可以包含U程l?在Java的应用程序中,最高层的线E组是名位main的线E组,在main中还可以加入U程或线E组,在mian的子U程l中也可以加入线E和U程l?形成U程l和U程之间的树(wi)状承关pR像上面创徏的线E都是属于mainq个U程l的?br />借用上面的例子,main里面可以q样写:(x)

public static void main(String[] args)
{
/***************************************
ThreadGroup(String name)
ThreadGroup(ThreadGroup parent, String name)
***********************************/
ThreadGroup group1=new ThreadGroup("group1");
ThreadGroup group2=new ThreadGroup(group1,"group2");
Thread t1=new Thread(group2,new MyThread());
Thread t2=new Thread(group2,new MyThread());
Thread t3=new Thread(group2,new MyThread());
t1.start();
t2.start();
t3.start();
}




U程l的嵌套Qt1,t2,t3被加入group2,group2加入group1?br />另外一个比较多是关于U程同步斚w的,试想q样一U情况,你有一W存?gu)Ƒ֜银行Q你在一安行ؓ(f)你的账户存款Q而你的妻子在另一安行从q个账户提款Q现在你?000块在你的账户里面。你存入?000Q但是由于另一方也在对q笔存款q行操作Qh家开始执行的时候只看到账户里面原来?000元,当你的妻子提?000元后Q你d所在的银行pZ的̎户里面没有钱了,而你所在的银行却认Zq有2000元?br />看看下面的例子:(x)

class BlankSaving //储蓄账户
{
private static int money=10000;
public void add(int i)
{
money=money+i;
System.out.println("Husband 向银行存入了 [K?+i+"]");
}
public void get(int i)
{
money=money-i;
System.out.println("Wife 向银行取C [K?+i+"]");
if(money<0)
System.out.println("余额不Q?);
}
public int showMoney()
{
return money;
}
}


class Operater implements Runnable
{
String name;
BlankSaving bs;
public Operater(BlankSaving b,String s)
{
name=s;
bs=b;



}
public static void oper(String name,BlankSaving bs)
{



if(name.equals("husband"))
{
try
{
for(int i=0;i<10;i++)
{
Thread.currentThread().sleep((int)(Math.random()*300));
bs.add(1000);
}
}catch(InterruptedException e){}
}else
{
try
{



for(int i=0;i<10;i++)
{
Thread.currentThread().sleep((int)(Math.random()*300));
bs.get(1000);
}
}catch(InterruptedException e){}
}
}
public void run()
{
oper(name,bs);
}
}
public class BankTest
{
public static void main(String[] args)throws InterruptedException
{
BlankSaving bs=new BlankSaving();
Operater o1=new Operater(bs,"husband");
Operater o2=new Operater(bs,"wife");
Thread t1=new Thread(o1);
Thread t2=new Thread(o2);
t1.start();
t2.start();
Thread.currentThread().sleep(500);
}



}




下面是其中一ơ的执行l果Q?br />


---------first--------------
Husband 向银行存入了 [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Husband 向银行存入了 [K?000]
Wife 向银行取C [K?000]
Husband 向银行存入了 [K?000]
Wife 向银行取C [K?000]
Husband 向银行存入了 [K?000]
Wife 向银行取C [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Wife 向银行取C [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Husband 向银行存入了 [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Husband 向银行存入了 [K?000]


看到了吗Q这可不是正的需求,在husbandq没有结束操作的时候,wife插了进来,q样很可能导致意外的l果。解军_法很单,是对数据q行操作Ҏ(gu)声明为synchronized,当方法被该关键字声明后,也就意味着Q如果这个数据被加锁Q只有一个对象得到这个数据的锁的时候该对象才能对这个数据进行操作。也是当你存款的时候,q笔账户在其他地Ҏ(gu)不能q行操作的,只有你存?gu)Ƒ֮毕,银行理人员̎戯锁,其他人才能对q个账户q行操作?br />修改public static void oper(String name,BlankSaving bs)为public static void oper(String name,BlankSaving bs)Q再看看l果:

Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Husband 向银行存入了 [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]
Wife 向银行取C [K?000]




当丈夫完成操作后Q妻子才开始执行操作,q样的话Q对׃n对象的操作就不会(x)有问题了?br />[wait and notify]
你可以利用这两个Ҏ(gu)很好的控制线E的执行程Q当U程调用waitҎ(gu)后,U程被挂vQ直到被另一U程唤醒QnotifyQ或则是如果waitҎ(gu)指定有时间得话,在没有被唤醒的情况下Q指定时间时间过后也自动被唤醒。但是要注意一定,被唤醒ƈ不是指马上执行,而是从组塞状态变为可q行状态,其是否运行还要看cpu的调度?br />事例代码Q?br />

class MyThread_1 extends Thread
{
Object lock;
public MyThread_1(Object o)
{
lock=o;
}
public void run()
{
try
{
synchronized(lock)
{
System.out.println("Enter Thread_1 and wait");
lock.wait();
System.out.println("be notified");
}
}catch(InterruptedException e){}
}
}
class MyThread_2 extends Thread
{
Object lock;
public MyThread_2(Object o)
{
lock=o;
}
public void run()
{
synchronized(lock)
{
System.out.println("Enter Thread_2 and notify");
lock.notify();
}
}
}
public class MyThread
{
public static void main(String[] args)
{
int[] in=new int[0];//notice
MyThread_1 t1=new MyThread_1(in);
MyThread_2 t2=new MyThread_2(in);
t1.start();
t2.start();
}
}

执行l果如下Q?br />Enter Thread_1 and wait
Enter Thread_2 and notify
Thread_1 be notified


可能你注意到了在使用wait and notifyҎ(gu)得时候我使用了synchronized块来包装q两个方法,q是׃调用q两个方法的时候线E必获得锁Q也是上面代码中的lock[]Q如果你不用synchronized包装q两个方法的得话Q又或则锁不一是同一把,比如在MyThread_2中synchronized(lock)改ؓ(f)synchronized(this),那么执行q个E序的时候将?x)抛出java.lang.IllegalMonitorStateException执行期异常。另外wait and notifyҎ(gu)是Object中的Qƈ不在Threadq个cM。最后你可能注意Cq点Qint[] in=new int[0];Z么不是创建new Object而是一?长度的数l,那是因ؓ(f)在java中创Z?长度的数l来充当锁更加高效?br />
Thread作ؓ(f)java中一重要l成部分Q当然还有很多地斚w要更深刻的认识,上面只是对Thread的一些常识和易错问题做了一个简要的ȝQ若要真正的掌握java的线E,q需要自己多做ȝ



joeyeezhang 2006-12-26 22:45 发表评论
]]>
synchronized的用?/title><link>http://www.aygfsteel.com/joeyeezhang/archive/2006/12/22/89606.html</link><dc:creator>joeyeezhang</dc:creator><author>joeyeezhang</author><pubDate>Fri, 22 Dec 2006 15:02:00 GMT</pubDate><guid>http://www.aygfsteel.com/joeyeezhang/archive/2006/12/22/89606.html</guid><wfw:comment>http://www.aygfsteel.com/joeyeezhang/comments/89606.html</wfw:comment><comments>http://www.aygfsteel.com/joeyeezhang/archive/2006/12/22/89606.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/joeyeezhang/comments/commentRss/89606.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/joeyeezhang/services/trackbacks/89606.html</trackback:ping><description><![CDATA[<p>synchronized 关键字,它包括两U用法:(x)synchronized Ҏ(gu)?synchronized 块?br />1. synchronized Ҏ(gu)Q通过在方法声明中加入 synchronized关键字来声明 synchronized Ҏ(gu)。如Q?br />public synchronized void accessVal(int newVal);<br />synchronized Ҏ(gu)控制对类成员变量的访问:(x)每个cd例对应一把锁Q每?synchronized Ҏ(gu)都必获得调用该Ҏ(gu)的类实例的锁方能执行Q否则所属线E阻塞,Ҏ(gu)一旦执行,q占该锁,直到从该Ҏ(gu)q回时才锁释放Q此后被d的线E方能获得该锁,重新q入可执行状态。这U机制确保了同一时刻对于每一个类实例Q其所有声明ؓ(f) synchronized 的成员函C臛_只有一个处于可执行状态(因ؓ(f)臛_只有一个能够获得该cd例对应的锁)Q从而有效避免了cL员变量的讉K冲突Q只要所有可能访问类成员变量的方法均被声明ؓ(f) synchronizedQ?br />?Java 中,不光是类实例Q每一个类也对应一把锁Q这h们也可将cȝ静态成员函数声明ؓ(f) synchronized Q以控制其对cȝ静态成员变量的讉K?br />synchronized Ҏ(gu)的缺P(x)若将一个大的方法声明ؓ(f)synchronized 会(x)大大影响效率Q典型地Q若线E类的方?run() 声明?synchronized Q由于在U程的整个生命期内它一直在q行Q因此将D它对本类M synchronized Ҏ(gu)的调用都永远不会(x)成功。当然我们可以通过访问类成员变量的代码放C门的Ҏ(gu)中,其声明?synchronized Qƈ在主Ҏ(gu)中调用来解决q一问题Q但?Java 为我们提供了更好的解军_法,那就?synchronized 块?br />2. synchronized 块:(x)通过 synchronized关键字来声明synchronized 块。语法如下:(x) <br />synchronized(syncObject) <br />synchronized 块是q样一个代码块Q其中的代码必须获得对象 syncObject Q如前所qͼ可以是类实例或类Q的锁方能执行,具体机制同前所q。由于可以针对Q意代码块Q且可Q意指定上锁的对象Q故灉|性较高?</p> <p>notify()?qing)notifyAll()是Object的方?与Object的wait()Ҏ(gu)配合使用,而且q三个方法必d同步块中调用.</p> <p>如下:<br />在线E?中执行如下代?br />...<br />synchronized(obj1)      //1.q入同步?br />{<br />    try {<br />    ...<br />    obj1.wait();        //2.q入暂停状?br />    }catch (InterruptedException exp) {}<br />}</p> <p>1.当前同步对象(monitor)为obj1,obj1是Q一实例,若是同步Ҏ(gu),则同步对象是this.q入同步块后,obj1为锁定状?锁定状态对obj1本n无Q何媄(jing)?而其它线E执行到同一代码?因不能获得锁,处于Block状?一旦解?被block的线E自动l执?<br />2.调用obj1.wait()有两个作?一是ɾU程q入{待状?二是解锁obj1,q时被block的线E将获得?U程1要退出等待必要由其它线E显式的调用obj1.notify()或notifyAll()Ҏ(gu).</p> <p>?/p> <p>...<br />synchronized(obj1)<br />{<br />    ...<br />    obj1.notify();    //3. 向wait的线E发通知信息<br />    ...<br />}<br />...</p> <p>若其它线E执行到此时,U程1处于wait状?则wait状态解?解除?若线E?若得到锁pl箋执行,若有多个U程处于obj1的wait状?notify随机选一个线E激z?而notifyAll是同时解除所有的wait状?<br />notifyAll()让等待某个对象K的所有线E离开d状态,<br />notify()随机地选取{待某个对象K的线E,让它dd状态?br /><br />notify(),notifyAll()非常有用Q在一个synchronized(lockObj)块中当调用lockObj.wait()ӞU程已l将锁放开来了Q这时当另外一个线E调用lockObj.notify()Ӟ{待的线E就?x)l执行下M。这是一U非帔R效的U程同步机制。如果没有他Q用sleep()来同步的话就太浪Ҏ(gu)间了?br />一个简单的例子Q?br />thread1 receive data<br />thread2 pase received data <br />lockObj是buf<br />当buf中没有数据时Qthread2中调用buf.wait释放锁,让thread1有机?x)执行?br />当thread1收到数据Ӟ调用buf.notify()通知thread1d理收到的数据?br /><br />如果在同步块入口炚w?不须其它U程调用notify(),调了也没效果,同步块能自动获得?/p> <p>如果是wait造成了阻?ȝnotfiy()Ȁz?q两个方法是配合使用<br /><br /><strong>notify、notifyAll、wait :</strong><br />主要是ؓ(f)了解x有监视器钥匙的线E暂停等待另一U程完成时可能发生死锁的问题。wait()Ҏ(gu)使调用线E等待,直到发生时或另一U程调用同一对象的notifyQ)或notifyAll()Ҏ(gu)。wait() Ҏ(gu)的用法如下:(x)wait()或wait(long timeoutPeriodInMilliseconds)前者等待被通知Q后者等待超时或通知。线E调用wait()Ҏ(gu)Ӟ释放所持有的钥匙让另一{待U程q入监视区。notify()Ҏ(gu)只唤醒一个等待线E,而notifyAll()唤醒所有等待该监视器的U程。注意,q些Ҏ(gu)只能在监视区内调用。否则会(x)输出一URuntimeExceptioncd的IllegaMonitorStateException异常状态?br />够详l清楚的吧?br />      Mwait()让线E等待,notify()和notifyall()ȀzL个等待线E,其实是撤销该线E的中断状态,从而他们有机?x)再ơ运?br />       有时?x)遇到如下问?E序的一部分在写数据,另一部分L?但有时会(x)出现读部分超前写部分,<br />q就是典型的产生?消耗者问?<br />   .wait:是一个线E睡?直到在相同的对象上调用notify或notifyAll<br />   .notify:启动W一个在相同对象调用wait的线E?br />   .notifyAll:启动在相同的对象调用wait的所有线E?/p><p><a >爱卖?/a><br /></p><img src ="http://www.aygfsteel.com/joeyeezhang/aggbug/89606.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/joeyeezhang/" target="_blank">joeyeezhang</a> 2006-12-22 23:02 <a href="http://www.aygfsteel.com/joeyeezhang/archive/2006/12/22/89606.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的Collectionc?http://www.aygfsteel.com/joeyeezhang/archive/2006/12/21/89380.htmljoeyeezhangjoeyeezhangThu, 21 Dec 2006 14:48:00 GMThttp://www.aygfsteel.com/joeyeezhang/archive/2006/12/21/89380.htmlhttp://www.aygfsteel.com/joeyeezhang/comments/89380.htmlhttp://www.aygfsteel.com/joeyeezhang/archive/2006/12/21/89380.html#Feedback0http://www.aygfsteel.com/joeyeezhang/comments/commentRss/89380.htmlhttp://www.aygfsteel.com/joeyeezhang/services/trackbacks/89380.htmlCollection
?em>List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
?em>Set
Map
├Hashtable
├HashMap
└WeakHashMap

Collection接口
  Collection是最基本的集合接口,一个Collection代表一lObjectQ即Collection的元素(ElementsQ。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接承自Collection的类QJava SDK提供的类都是l承自Collection的“子接口”如List和Set?br />  所有实现Collection接口的类都必L供两个标准的构造函敎ͼ(x)无参数的构造函数用于创Z个空的CollectionQ有一个Collection参数的构造函数用于创Z个新的CollectionQ这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection?br />  如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个P代子Q用该q代子即可逐一讉KCollection中每一个元素。典型的用法如下Q?br />    Iterator it = collection.iterator(); // 获得一个P代子
    while(it.hasNext()) {
      Object obj = it.next(); // 得到下一个元?br />    }

  由Collection接口z的两个接口是List和Set?/p>

List接口
  List是有序的CollectionQ用此接口能够_的控制每个元素插入的位置。用戯够用烦(ch)引(元素在List中的位置Q类g数组下标Q来讉KList中的元素Q这cM于Java的数l?br />和下面要提到的Set不同QList允许有相同的元素?br />  除了hCollection接口必备的iterator()Ҏ(gu)外,Listq提供一个listIterator()Ҏ(gu)Q返回一个ListIterator接口Q和标准的Iterator接口相比QListIterator多了一些add()之类的方法,允许dQ删除,讑֮元素Q还能向前或向后遍历?br />  实现List接口的常用类有LinkedListQArrayListQVector和Stack?/p>

LinkedListc?/strong>
  LinkedList实现了List接口Q允许null元素。此外LinkedList提供额外的getQremoveQinsertҎ(gu)在LinkedList的首部或N。这些操作LinkedList可被用作堆栈QstackQ,队列QqueueQ或双向队列QdequeQ?br />  注意LinkedList没有同步Ҏ(gu)。如果多个线E同时访问一个ListQ则必须自己实现讉K同步。一U解x法是在创建List时构造一个同步的ListQ?br />    List list = Collections.synchronizedList(new LinkedList(...));

ArrayListc?/strong>
  ArrayList实现了可变大的数组。它允许所有元素,包括null。ArrayList没有同步?br />sizeQisEmptyQgetQsetҎ(gu)q行旉为常数。但是addҎ(gu)开销为分摊的常数Q添加n个元素需要O(n)的时间。其他的Ҏ(gu)q行旉为线性?br />  每个ArrayList实例都有一个容量(CapacityQ,即用于存储元素的数组的大。这个容量可随着不断d新元素而自动增加,但是增长法q没有定义。当需要插入大量元素时Q在插入前可以调用ensureCapacityҎ(gu)来增加ArrayList的容量以提高插入效率?br />  和LinkedList一PArrayList也是非同步的QunsynchronizedQ?/p>

Vectorc?/strong>
  Vector非常cMArrayListQ但是Vector是同步的。由Vector创徏的IteratorQ虽然和ArrayList创徏的Iterator是同一接口Q但是,因ؓ(f)Vector是同步的Q当一个Iterator被创且正在被用,另一个线E改变了Vector的状态(例如Q添加或删除了一些元素)Q这时调用Iterator的方法时抛出ConcurrentModificationExceptionQ因此必L莯异常?/p>

Stack c?/font>
  Stackl承自VectorQ实C个后q先出的堆栈。Stack提供5个额外的Ҏ(gu)使得Vector得以被当作堆栈用。基本的push和popҎ(gu)Q还有peekҎ(gu)得到栈顶的元素,emptyҎ(gu)试堆栈是否为空QsearchҎ(gu)(g)一个元素在堆栈中的位置。Stack刚创建后是空栈?/p>

Set接口
  Set是一U不包含重复的元素的CollectionQ即L的两个元素e1和e2都有e1.equals(e2)=falseQSet最多有一个null元素?br />  很明显,Set的构造函数有一个约束条Ӟ传入的Collection参数不能包含重复的元素?br />  h意:(x)必须心操作可变对象QMutable ObjectQ。如果一个Set中的可变元素改变了自w状态导致Object.equals(Object)=true导致一些问题?/p>

Map接口
  h意,Map没有l承Collection接口QMap提供key到value的映。一个Map中不能包含相同的keyQ每个key只能映射一个value。Map接口提供3U集合的视图QMap的内容可以被当作一lkey集合Q一lvalue集合Q或者一lkey-value映射?/p>

Hashtablec?/strong>
  Hashtablel承Map接口Q实C个key-value映射的哈希表。Q何非I(non-nullQ的对象都可作ؓ(f)key或者value?br />  d数据使用put(key, value)Q取出数据用get(key)Q这两个基本操作的时间开销为常数?br />Hashtable通过initial capacity和load factor两个参数调整性能。通常~省的load factor 0.75较好地实C旉和空间的均衡。增大load factor可以节省I间但相应的查找旉增大,q会(x)影响像get和putq样的操作?br />使用Hashtable的简单示例如下,?Q?Q?攑ֈHashtable中,他们的key分别是”one”,”two”,”three”:(x)
    Hashtable numbers = new Hashtable();
    numbers.put(“one? new Integer(1));
    numbers.put(“two? new Integer(2));
    numbers.put(“three? new Integer(3));

  要取Z个数Q比?Q用相应的keyQ?br />    Integer n = (Integer)numbers.get(“two?;
    System.out.println(“two = ?+ n);

  ׃作ؓ(f)key的对象将通过计算其散列函数来定与之对应的value的位|,因此M作ؓ(f)key的对象都必须实现hashCode和equalsҎ(gu)。hashCode和equalsҎ(gu)l承自根cObjectQ如果你用自定义的类当作key的话Q要相当心Q按照散列函数的定义Q如果两个对象相同,即obj1.equals(obj2)=trueQ则它们的hashCode必须相同Q但如果两个对象不同Q则它们的hashCode不一定不同,如果两个不同对象的hashCode相同Q这U现象称为冲H,冲突?x)导致操作哈希表的时间开销增大Q所以尽量定义好的hashCode()Ҏ(gu)Q能加快哈希表的操作?br />  如果相同的对象有不同的hashCodeQ对哈希表的操作?x)出现意想不到的l果Q期待的getҎ(gu)q回nullQ,要避免这U问题,只需要牢C条:(x)要同时复写equalsҎ(gu)和hashCodeҎ(gu)Q而不要只写其中一个?br />  Hashtable是同步的?/p>

HashMapc?/font>
  HashMap和HashtablecMQ不同之处在于HashMap是非同步的,q且允许nullQ即null value和null key。,但是HashMap视ؓ(f)CollectionӞvalues()Ҏ(gu)可返回CollectionQ,其P代子操作旉开销和HashMap的容量成比例。因此,如果q代操作的性能相当重要的话Q不要将HashMap的初始化定w讑־q高Q或者load factorq低?/p>

WeakHashMapc?/strong>
  WeakHashMap是一U改q的HashMapQ它对key实行“弱引用”,如果一个key不再被外部所引用Q那么该key可以被GC回收?/p>

ȝ
  如果涉及(qing)到堆栈,队列{操作,应该考虑用ListQ对于需要快速插入,删除元素Q应该用LinkedListQ如果需要快速随问元素,应该使用ArrayList?br />  如果E序在单U程环境中,或者访问仅仅在一个线E中q行Q考虑非同步的c,其效率较高,如果多个U程可能同时操作一个类Q应该用同步的cR?br />  要特别注意对哈希表的操作Q作为key的对象要正确复写equals和hashCodeҎ(gu)?br />  量q回接口而非实际的类型,如返回List而非ArrayListQ这样如果以后需要将ArrayList换成LinkedListӞ客户端代码不用改变。这是针对抽象~程?/p>

joeyeezhang 2006-12-21 22:48 发表评论
]]>
վ֩ģ壺 | ʡ| | Ϫ| ǭ| | | ľ| | ʯ| | ²| ̨| | ͻȪ| Ӽ| | | | ʡ| ͩ| ˻| | ˮ| ¡| ƽ| | | | | | | ɽ| | Ĵʡ| | ʯ| | | | |