??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久久久a亚洲欧洲aⅴ,久久综合亚洲色hezyo,亚洲第一精品福利http://www.tkk7.com/tinysun/category/37793.htmlzh-cnSat, 11 Sep 2010 09:44:41 GMTSat, 11 Sep 2010 09:44:41 GMT60U程中释N的方?/title><link>http://www.tkk7.com/tinysun/archive/2010/09/10/331658.html</link><dc:creator>何克?/dc:creator><author>何克?/author><pubDate>Fri, 10 Sep 2010 05:51:00 GMT</pubDate><guid>http://www.tkk7.com/tinysun/archive/2010/09/10/331658.html</guid><wfw:comment>http://www.tkk7.com/tinysun/comments/331658.html</wfw:comment><comments>http://www.tkk7.com/tinysun/archive/2010/09/10/331658.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tinysun/comments/commentRss/331658.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tinysun/services/trackbacks/331658.html</trackback:ping><description><![CDATA[# 调用obj的wait(), notify()Ҏ(gu)前,必须获得obj锁,也就是必d在synchronized(obj) {...} 代码D内?br /> <br /> # <strong>调用obj.wait()后,U程A释放了(jin)obj的锁Q?/strong>否则U程B无法获得obj锁,也就无法在synchronized(obj) {...} 代码D内唤醒A?br /> <br /> # 当obj.wait()Ҏ(gu)q回后,U程A需要再ơ获得obj锁,才能l箋执行?br /> <br /> # 如果A1,A2,A3都在obj.wait()Q则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM军_Q?br /> <br /> # obj.notifyAll()则能全部唤醒A1,A2,A3Q但是要l箋执行obj.wait()的下一条语句,必须获得obj锁,因此QA1,A2,A3只有一个有Z(x)获得锁l执行,例如A1Q其余的需要等待A1释放obj锁之后才能l执行?br /> <br /> # 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此QA1,A2,A3虽被唤醒Q但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后QA1,A2,A3中的一个才有机?x)获得锁l箋执行?br /> <br /> wait()/sleep()的区?br /> <br /> 前面讲了(jin)wait/notify机制QThreadq有一个sleep()?rn)态方法,它也能ɾU程暂停一D|间?strong>sleep与wait的不同点是:(x)sleepq不释放锁,q且sleep的暂停和wait暂停是不一L(fng)。obj.wait?x)ɾU程q入obj对象的等待集合中q等待唤醒?br /> </strong>  <br /> <strong>但是wait()和sleep()都可以通过interrupt()Ҏ(gu)打断U程的暂停状态,从而ɾU程立刻抛出InterruptedException?br /> </strong>  <br /> 如果U程A希望立即l束U程BQ则可以对线EB对应的Thread实例调用interruptҎ(gu)。如果此ȝEB正在wait/sleep /joinQ则U程B?x)立L出InterruptedExceptionQ在catch() {} 中直接return卛_安全地结束线E?br /> <br /> 需要注意的是,InterruptedException是线E自׃内部抛出的,q不是interrupt()Ҏ(gu)抛出的。对某一U程调用 interrupt()Ӟ如果该线E正在执行普通的代码Q那么该U程Ҏ(gu)׃?x)抛出InterruptedException。但是,一旦该U程q入? wait()/sleep()/join()后,׃(x)立刻抛出InterruptedException? <img src ="http://www.tkk7.com/tinysun/aggbug/331658.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tinysun/" target="_blank">何克?/a> 2010-09-10 13:51 <a href="http://www.tkk7.com/tinysun/archive/2010/09/10/331658.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaU程http://www.tkk7.com/tinysun/archive/2010/09/10/331651.html何克?/dc:creator>何克?/author>Fri, 10 Sep 2010 05:42:00 GMThttp://www.tkk7.com/tinysun/archive/2010/09/10/331651.htmlhttp://www.tkk7.com/tinysun/comments/331651.htmlhttp://www.tkk7.com/tinysun/archive/2010/09/10/331651.html#Feedback0http://www.tkk7.com/tinysun/comments/commentRss/331651.htmlhttp://www.tkk7.com/tinysun/services/trackbacks/331651.html

1》:(x)_的JavaU程Sleep,yield,wait,notify,Synchronized

 

多线E?br /> U程Q是指进E中的一个执行流E?br /> U程与进E的区别Q每个进E都需要操作系lؓ(f)其分配独立的内存地址I间Q而同一q程中的所有线E在同一块地址I间中工作,q些U程可以׃n同一块内存和p? l资源?br />

如何创徏一个线E?

创徏U程有两U方式,如下Q?br /> 1?扩展java.lang.Threadc?br /> 2?实现Runnable接口
ThreadcM表线E类Q它的两个最主要的方法是Q?br /> run()——包含线E运行时所执行的代?br /> Start()——用于启动线E?br />
一个线E只能被启动一ơ。第二次启动时将?x)抛出java.lang.IllegalThreadExcetpion异常

U程间状态的转换Q如囄Q?br />
新徏状态:(x)用new语句创徏的线E对象处于新建状态,此时它和其它的java对象一P仅仅在堆中被分配?jin)内?br /> qA状态:(x)当一个线E创Z(jin)以后Q其他的U程调用?jin)它的start()Ҏ(gu)Q该U程p入了(jin)qA状态。处于这个状态的U程位于可运行池中,{待获得CPU 的用权
q行状态:(x)处于q个状态的U程占用CPU,执行E序的代?br /> d状态:(x)当线E处于阻塞状态时Qjava虚拟Z?x)给U程分配CPUQ直到线E重新进入就l状态,它才有机?x){到运行状态?br /> d状态分ZU情况:(x)
1? 位于对象{待池中的阻塞状态:(x)当线E运行时Q如果执行了(jin)某个对象的wait()Ҏ(gu)Qjava虚拟机就回把U程攑ֈq个对象的等待池?br /> 2? 位于对象锁中的阻塞状态,当线E处于运行状态时Q试图获得某个对象的同步锁时Q如果该对象的同步锁已经被其他的U程占用QJVM׃(x)把这个线E放到这个对 象的琐池中?br /> 3? 其它的阻塞状态:(x)当前U程执行?jin)sleep()Ҏ(gu)Q或者调用了(jin)其它U程的join()Ҏ(gu)Q或者发Z(jin)I/OhӞ׃(x)q入q个状态中?br />
M状态:(x)当线E退Z(jin)run()Ҏ(gu)Q就q入?jin)死亡状态,该线E结束了(jin)生命周期?br /> 或者正帔R?br /> 或者遇到异帔R?br /> ThreadcȝisAlive()Ҏ(gu)判断一个线E是否活着Q当U程处于M状态或者新建状态时Q该Ҏ(gu)q回false,在其余的状态下Q该Ҏ(gu)q回 true.

U程调度
U程调度模型Q分时调度模型和抢占式调度模?br /> JVM采用抢占式调度模型?br /> 所谓的多线E的q发q行Q其实是指宏观上看,各个U程轮流获得CPU的用权Q分别执行各自的d?br /> Q线E的调度不是跨^収ͼ它不仅取决于java虚拟机,它还依赖于操作系l)(j)

如果希望明确地让一个线E给另外一个线E运行的Z(x)Q可以采取以下的办法之一
1?调整各个U程的优先
2?让处于运行状态的U程调用Thread.sleep()Ҏ(gu)
3?让处于运行状态的U程调用Thread.yield()Ҏ(gu)
4?让处于运行状态的U程调用另一个线E的join()Ҏ(gu)

调整各个U程的优先
ThreadcȝsetPriority(int)和getPriority()Ҏ(gu)分别用来讄优先U和d优先U?br /> 如果希望E序能够Ud到各个操作pȝ中,应该保在设|线E的优先U时Q只使用MAX_PRIORITY、NORM_PRIORITY? MIN_PRIORITYq?个优先?br />
U程睡眠Q当U程在运行中执行?jin)sleep()Ҏ(gu)Ӟ它就?x)放弃CPUQ{到阻塞状态?br /> U程让步Q当U程在运行中执行?jin)Threadcȝyield()?rn)态方法时Q如果此时具有相同优先的其它线E处于就l状态,那么yield()Ҏ(gu)把 当前q行的线E放到运行池中ƈ使另一个线E运行。如果没有相同优先的可q行U程Q则yield()Ҏ(gu)什么也不做?br /> Sleep()Ҏ(gu)和yield()Ҏ(gu)都是Threadcȝ?rn)态方法,都会(x)使当前处于运行状态的U程攑ּCPUQ把q行Z(x)让给别的U程Q两者的区别? 于:(x)
1、sleep()Ҏ(gu)?x)给其他U程q行的机?x),而不考虑其他U程的优先Q因此会(x)l较低线E一个运行的Z(x)Qyield()Ҏ(gu)只会(x)l相同优先或者更 高优先的线E一个运行的Z(x)?br /> 2、当U程执行?jin)sleep(long millis)Ҏ(gu)后,{到阻塞状态,参数millis指定睡眠旉Q当U程执行?jin)yield()Ҏ(gu)后,{到就l状态?br /> 3、sleep()Ҏ(gu)声明抛出InterruptedException异常Q而yield()Ҏ(gu)没有声明抛出M异常
4、sleep()Ҏ(gu)比yield()Ҏ(gu)h更好的移植?br />
{待其它U程的结束:(x)join()
当前q行的线E可以调用另一个线E的 join()Ҏ(gu)Q当前运行的U程{到阻塞状态,直到另一个线E运行结束,它才恢复q行?br />
定时器Timer:在JDK的java.util包中提供?jin)一个实用类Timer, 它能够定时执行特定的d?br />
U程的同?br /> 原子操作Q根据Java规范Q对于基本类型的赋值或者返回值操作,是原子操作。但q里的基本数据类型不包括long和double, 因ؓ(f)JVM看到的基本存储单位是32位,而long 和double都要?4位来表示。所以无法在一个时钟周期内完成?br />
自增操作Q?+Q不是原子操作,因ؓ(f)它涉?qing)到一ơ读和一ơ写?br />
原子操作Q由一l相关的操作完成Q这些操作可能会(x)操纵与其它的U程׃n的资源,Z(jin)保证得到正确的运结果,一个线E在执行原子操作光Q应该采取其他的 措施使得其他的线E不能操U共享资源?br />
同步代码块:(x)Z(jin)保证每个U程能够正常执行原子操作QJava引入?jin)同步机Ӟ具体的做法是在代表原子操作的E序代码前加上synchronized? 讎ͼq样的代码被UCؓ(f)同步代码块?br />
同步锁:(x)每个JAVA对象都有且只有一个同步锁Q在M时刻Q最多只允许一个线E拥有这把锁?br />
当一个线E试图访问带有synchronized(this)标记的代码块Ӟ必须获得 this关键字引用的对象的锁Q在以下的两U情况下Q本U程有着不同的命q?br /> 1? 假如q个锁已l被其它的线E占用,JVM׃(x)把这个线E放到本对象的锁池中。本U程q入d状态。锁池中可能有很多的U程Q等到其他的U程释放? 锁,JVM׃(x)从锁池中随机取出一个线E,使这个线E拥有锁Qƈ且{到就l状态?br /> 2?假如q个锁没有被其他U程占用Q本U程?x)获得这把锁Q开始执行同步代码块?br /> Q一般情况下在执行同步代码块时不?x)释攑֐步锁Q但也有Ҏ(gu)情况?x)释攑֯象?br /> 如在执行同步代码块时Q遇到异常而导致线E终止,锁会(x)被释放;在执行代码块Ӟ执行?jin)锁所属对象的wait()Ҏ(gu)Q这个线E会(x)释放对象锁,q入对象的等 待池中)(j)

U程同步的特征:(x)
1? 如果一个同步代码块和非同步代码块同时操作共享资源,仍然?x)造成对共享资源的竞争。因为当一个线E执行一个对象的同步代码块时Q其他的U程仍然可以执行? 象的非同步代码块。(所谓的U程之间保持同步Q是指不同的U程在执行同一个对象的同步代码块时Q因获得对象的同步锁而互相牵Ӟ(j)
2?每个对象都有唯一的同步锁
3?在静(rn)态方法前面可以用synchronized修饰W?br /> 4? 当一个线E开始执行同步代码块Ӟq不意味着必须以不间断的方式运行,q入同步代码块的U程可以执行Thread.sleep()或者执? Thread.yield()Ҏ(gu)Q此时它q不释放对象锁,只是把运行的Z(x)让给其他的线E?br /> 5? Synchronized声明不会(x)被承,如果一个用synchronized修饰的方法被子类覆盖Q那么子cMq个Ҏ(gu)不在保持同步Q除非用 synchronized修饰?br />
U程安全的类Q?br /> 1?q个cȝ对象可以同时被多个线E安全的讉K?br /> 2?每个U程都能正常的执行原子操作,得到正确的结果?br /> 3?在每个线E的原子操作都完成后Q对象处于逻辑上合理的状态?br />
释放对象的锁Q?br /> 1?执行完同步代码块׃(x)释放对象的锁
2?在执行同步代码块的过E中Q遇到异常而导致线E终止,锁也?x)被释?br /> 3?在执行同步代码块的过E中Q执行了(jin)锁所属对象的wait()Ҏ(gu)Q这个线E会(x)释放对象锁,q入对象的等待池?br />
死锁
当一个线E等待由另一个线E持有的锁,而后者正在等待已被第一个线E持有的锁时Q就?x)发生死锁。JVM不监也不试N免这U情况,因此保证不发生死锁就 成了(jin)E序员的责Q?br />
如何避免死锁
一个通用的经验法则是Q当几个U程都要讉K׃n资源A、B、C Ӟ保证每个U程都按照同L(fng)序去访问他们?br />
U程通信
Java.lang.ObjectcM提供?jin)两个用于线E通信的方?br /> 1?wait():执行?jin)该?gu)的线E释攑֯象的锁,JVM?x)把该线E放到对象的{待池中。该U程{待其它U程唤醒
2? notify():执行该方法的U程唤醒在对象的{待池中{待的一个线E,JVM从对象的{待池中随机选择一个线E,把它转到对象的锁池中?/font>

 

 

 

Q》:(x)U程同步

我们可以在计机上运行各U计机软gE序。每一个运行的E序可能包括多个独立q行的线E(ThreadQ?br /> U程QThreadQ是一份独立运行的E序Q有自己专用的运行栈。线E有可能和其他线E共享一些资源,比如Q内存,文gQ数据库{?br /> 当多个线E同时读写同一份共享资源的时候,可能?x)引起冲H。这时候,我们需要引入线E?#8220;同步”机制Q即各位U程之间要有个先来后刎ͼ不能一H蜂挤上L作一团?br /> 同步q个词是从英文synchronizeQ同时发生Q翻译过来的。我也不明白Z么要用这个很Ҏ(gu)引v误解的词。既然大安q么用,׃也就只好q么就?br /> U程同步的真实意思和字面意思恰好相反。线E同步的真实意思,其实?#8220;排队”Q几个线E之间要排队Q一个一个对׃n资源q行操作Q而不是同时进行操作?br />
因此Q关于线E同步,需要牢牢记住的W一Ҏ(gu)Q线E同步就是线E排队。同步就是排队。线E同步的目的是避免U程“同步”执行。这可真是个无聊的绕口o(h)?br /> 关于U程同步Q需要牢牢记住的W二Ҏ(gu) “׃n”q两个字。只有共享资源的d讉K才需要同步。如果不是共享资源,那么根本没有同步的必要?br /> 关于U程同步Q需要牢牢记住的W三Ҏ(gu)Q只?#8220;变量”才需要同步访问。如果共享的资源是固定不变的Q那么就相当?#8220;帔R”Q线E同时读取常量也不需要同步。至一个线E修改共享资源,q样的情况下Q线E之间就需要同步?br /> 关于U程同步Q需要牢牢记住的W四Ҏ(gu)Q多个线E访问共享资源的代码有可能是同一份代码,也有可能是不同的代码Q无论是否执行同一份代码,只要q些U程的代码访问同一份可变的׃n资源Q这些线E之间就需要同步?br />
Z(jin)加深理解Q下面D几个例子?br /> 有两个采购员Q他们的工作内容是相同的Q都是遵循如下的步骤Q?br /> Q?Q到?jng)场上去Q寻扑ƈ购买有潜力的样品?br /> Q?Q回到公司,写报告?br /> q两个h的工作内容虽然一P他们都需要购买样品,他们可能买到同样U类的样品,但是他们l对不会(x)购买到同一件样品,他们之间没有M׃n资源。所以,他们可以各自q行自己的工作,互不q扰?br /> q两个采购员q当于两个U程Q两个采购员遵@相同的工作步骤,相当于这两个U程执行同一D代码?br />
下面l这两个采购员增加一个工作步骤。采购员需要根据公司的“布告?#8221;上面公布的信息,安排自己的工作计划?br /> q两个采购员有可能同时走到布告栏的前面,同时观看布告栏上的信息。这一炚w题都没有。因为布告栏是只ȝQ这两个采购员谁都不?x)去修改布告栏上写的信息?br />
下面增加一个角艌Ӏ一个办公室行政人员q个时候,也走C(jin)布告栏前面,准备修改布告栏上的信息?br /> 如果行政人员先到辑ָ告栏Qƈ且正在修改布告栏的内宏V两个采购员q个时候,恰好也到?jin)。这两个采购员就必须{待行政人员完成修改之后Q才能观看修改后的信息?br /> 如果行政人员到达的时候,两个采购员已l在观看布告栏了(jin)。那么行政h员需要等待两个采购员把当前信息记录下来之后,才能够写上新的信息?br /> 上述q两U情况,行政人员和采购员对布告栏的访问就需要进行同步。因为其中一个线E(行政人员Q修改了(jin)׃n资源Q布告栏Q。而且我们可以看到Q行政h员的 工作程和采购员的工作流E(执行代码Q完全不同,但是׃他们讉K?jin)同一份可变共享资源(布告栏)(j)Q所以他们之间需要同步?br />
同步?br />
前面讲了(jin)Z么要U程同步Q下面我们就来看如何才能U程同步?br /> U程同步的基本实现思\q是比较Ҏ(gu)理解的。我们可以给׃n资源加一把锁Q这把锁只有一把钥匙。哪个线E获取了(jin)q把钥匙Q才有权利访问该׃n资源?br /> 生活中,我们也可能会(x)遇到q样的例子。一些超?jng)的外面提供了(jin)一些自动储物箱。每个储物箱都有一把锁Q一把钥匙。h们可以用那些带有钥匙的储物,把东? 攑ֈ储物里面,把储物箱锁上Q然后把钥匙拿走。这P该储物箱p锁住?jin),其他Z能再讉Kq个储物。(当然Q真实的储物钥匙是可以被h拿走复制 的,所以不要把贵重物品攑֜市(jng)的储物箱里面。于是很多超?jng)都采用了(jin)?sh)子密码锁。)(j)
U程同步锁这个模型看h很直观。但是,q有一个严ȝ问题没有解决Q这个同步锁应该加在哪里Q?br /> 当然是加在共享资源上?jin)。反应快的读者一定会(x)抢先回答?br /> 没错Q如果可能,我们当然量把同步锁加在׃n资源上。一些比较完善的׃n资源Q比如,文gpȝQ数据库pȝ{,自n都提供了(jin)比较完善的同步锁机制。我们不用另外给q些资源加锁Q这些资源自己就有锁?br /> 但是Q大部分情况下,我们在代码中讉K的共享资源都是比较简单的׃n对象。这些对象里面没有地方让我们加锁?br /> 读者可能会(x)提出Qؓ(f)什么不在每一个对象内部都增加一个新的区域,专门用来加锁呢?q种设计理论上当然也是可行的。问题在于,U程同步的情况ƈ不是很普遍。如果因概率事Ӟ在所有对象内部都开辟一块锁I间Q将?x)带来极大的I间费。得不偿失?br /> 于是Q现代的~程语言的设计思\都是把同步锁加在代码D上。确切的_(d)是把同步锁加?#8220;讉K׃n资源的代码段”上。这一点一定要CQ同步锁是加在代码段上的?br /> 同步锁加在代码段上,很好地解决?jin)上q的I间费问题。但是却增加?jin)模型的复杂度,也增加?jin)我们的理解难度?br /> 现在我们来仔细分析“同步锁加在代码段?#8221;的线E同步模型?br /> 首先Q我们已l解决了(jin)同步锁加在哪里的问题。我们已l确定,同步锁不是加在共享资源上Q而是加在讉K׃n资源的代码段上?br /> 其次Q我们要解决的问题是Q我们应该在代码D上加什么样的锁。这个问题是重点中的重点。这是我们尤其要注意的问题:(x)讉K同一份共享资源的不同代码D,应该加上同一个同步锁Q如果加的是不同的同步锁Q那么根本就起不到同步的作用Q没有Q何意义?br /> q就是说Q同步锁本n也一定是多个U程之间的共享对象?br />
Java语言的synchronized关键?br />
Z(jin)加深理解QD几个代码D同步的例子?br /> 不同语言的同步锁模型都是一L(fng)。只是表达方式有些不同。这里我们以当前最行的Java语言Z。Java语言里面用synchronized关键字给代码D加锁。整个语法Ş式表Cؓ(f)
synchronized(同步? {
  // 讉K׃n资源Q需要同步的代码D?br /> }

q里其要注意的是Q同步锁本n一定要是共享的对象?br />
… f1() {

Object lock1 = new Object(); // 产生一个同步锁

synchronized(lock1){
  // 代码D?A
// 讉K׃n资源 resource1
// 需要同?br /> }
}

上面q段代码没有M意义。因为那个同步锁是在函数体内部生的。每个线E调用这D代码的时候,都会(x)产生一个新的同步锁。那么多个线E之_(d)使用的是不同的同步锁。根本达不到同步的目的?br /> 同步代码一定要写成如下的Ş式,才有意义?br />
public static final Object lock1 = new Object();

… f1() {

synchronized(lock1){ // lock1 是公用同步锁
  // 代码D?A
// 讉K׃n资源 resource1
// 需要同?br /> }

你不一定要把同步锁声明为static或者publicQ但是你一定要保证相关的同步代码之_(d)一定要使用同一个同步锁?br /> 讲到q里Q你一定会(x)好奇Q这个同步锁到底是个什么东ѝؓ(f)什么随便声明一个Object对象Q就可以作ؓ(f)同步锁?
在Java里面Q同步锁的概念就是这L(fng)。Q何一个Object Reference都可以作为同步锁。我们可以把Object Reference理解为对象在内存分配pȝ中的内存地址。因此,要保证同步代码段之间使用的是同一个同步锁Q我们就要保证这些同步代码段的synchronized关键字用的是同一个Object ReferenceQ同一个内存地址。这也是Z么我在前面的代码中声明lock1的时候,使用?jin)final关键字,q就是ؓ(f)?jin)保证lock1的Object Reference在整个系l运行过E中都保持不变?br /> 一些求知欲强的读者可能想要l深入了(jin)解synchronzied(同步?的实际运行机制。Java虚拟范中Q你可以在google?#8220;JVM Spec”{关键字q行搜烦(ch)Q,有对synchronized关键字的详细解释。synchronized?x)编译?monitor enter, … monitor exit之类的指令对。Monitor是实际上的同步锁。每一个Object Reference在概念上都对应一个monitor?br /> q些实现l节问题Qƈ不是理解同步锁模型的关键。我们l看几个例子Q加深对同步锁模型的理解?br />
public static final Object lock1 = new Object();

… f1() {

synchronized(lock1){ // lock1 是公用同步锁
  // 代码D?A
// 讉K׃n资源 resource1
// 需要同?br /> }
}

… f2() {

synchronized(lock1){ // lock1 是公用同步锁
  // 代码D?B
// 讉K׃n资源 resource1
// 需要同?br /> }
}

上述的代码中Q代码段A(ch)和代码段B是同步的。因为它们用的是同一个同步锁lock1?br /> 如果?0个线E同时执行代码段A(ch)Q同时还?0个线E同时执行代码段BQ那么这30个线E之间都是要q行同步的?br /> q?0个线E都要竞争一个同步锁lock1。同一时刻Q只有一个线E能够获得lock1的所有权Q只有一个线E可以执行代码段A(ch)或者代码段B。其他竞争失败的U程只能暂停q行Q进入到该同步锁的就l(ReadyQ队列?br /> 每一个同步锁下面都挂?jin)几个线E队列,包括qAQReadyQ队列,待召QWaitingQ队列等。比如,lock1对应的就l队列就可以叫做lock1 - ready queue。每个队列里面都可能有多个暂停运行的U程?br /> 注意Q竞争同步锁p|的线E进入的是该同步锁的qAQReadyQ队列,而不是后面要讲述的待召队列(Waiting QueueQ也可以译为等待队列)(j)。就l队列里面的U程L时刻准备着竞争同步锁,时刻准备着q行。而待召队列里面的U程则只能一直等待,直到{到某个信号的通知之后Q才能够转移到就l队列中Q准备运行?br /> 成功获取同步锁的U程Q执行完同步代码D之后,?x)释攑֐步锁。该同步锁的qA队列中的其他U程ql下一轮同步锁的竞争。成功者就可以l箋q行Q失败者还是要乖乖地待在就l队列中?br /> 因此Q线E同步是非常耗费资源的一U操作。我们要量控制U程同步的代码段范围。同步的代码D范围越越好。我们用一个名?#8220;同步_度”来表C同步代码段的范围?br /> 同步_度
在Java语言里面Q我们可以直接把synchronized关键字直接加在函数的定义上?br /> 比如?br /> … synchronized … f1() {
  // f1 代码D?br /> }

q段代码q价于
… f1() {
  synchronized(this){ // 同步锁就是对象本w?br />     // f1 代码D?br />   }
}

同样的原则适用于静(rn)态(staticQ函?br /> 比如?br /> … static synchronized … f1() {
  // f1 代码D?br /> }

q段代码q价于
…static … f1() {
  synchronized(Class.forName(…)){ // 同步锁是cd义本w?br />     // f1 代码D?br />   }
}

但是Q我们要量避免q种直接把synchronized加在函数定义上的h做法。因为我们要控制同步_度。同步的代码D越越好。synchronized控制的范围越越好?br /> 我们不仅要在~小同步代码D늚长度上下功夫Q我们同时还要注意细分同步锁?br /> 比如Q下面的代码

public static final Object lock1 = new Object();

… f1() {

synchronized(lock1){ // lock1 是公用同步锁
  // 代码D?A
// 讉K׃n资源 resource1
// 需要同?br /> }
}

… f2() {

synchronized(lock1){ // lock1 是公用同步锁
  // 代码D?B
// 讉K׃n资源 resource1
// 需要同?br /> }
}

… f3() {

synchronized(lock1){ // lock1 是公用同步锁
  // 代码D?C
// 讉K׃n资源 resource2
// 需要同?br /> }
}

… f4() {

synchronized(lock1){ // lock1 是公用同步锁
  // 代码D?D
// 讉K׃n资源 resource2
// 需要同?br /> }
}

上述?D同步代码,使用同一个同步锁lock1。所有调?D代码中M一D代码的U程Q都需要竞争同一个同步锁lock1?br /> 我们仔细分析一下,发现q是没有必要的?br /> 因ؓ(f)f1()的代码段A(ch)和f2()的代码段B讉K的共享资源是resource1Qf3()的代码段C和f4()的代码段D讉K的共享资源是 resource2Q它们没有必要都竞争同一个同步锁lock1。我们可以增加一个同步锁lock2。f3()和f4()的代码可以修改ؓ(f)Q?br /> public static final Object lock2 = new Object();

… f3() {

synchronized(lock2){ // lock2 是公用同步锁
  // 代码D?C
// 讉K׃n资源 resource2
// 需要同?br /> }
}

… f4() {

synchronized(lock2){ // lock2 是公用同步锁
  // 代码D?D
// 讉K׃n资源 resource2
// 需要同?br /> }
}

q样Qf1()和f2()׃(x)竞争lock1Q而f3()和f4()׃(x)竞争lock2。这P分开来分别竞争两个锁Q就可以大大较少同步锁竞争的概率Q从而减系l的开销?br />
信号?br />
同步锁模型只是最单的同步模型。同一时刻Q只有一个线E能够运行同步代码?br /> 有的时候,我们希望处理更加复杂的同步模型,比如生?消费者模型、读写同步模型等。这U情况下Q同步锁模型׃够用?jin)。我们需要一个新的模型。这是我们要讲q的信号量模型?br /> 信号量模型的工作方式如下Q线E在q行的过E中Q可以主动停下来Q等待某个信号量的通知Q这时候,该线E就q入到该信号量的待召QWaitingQ队列当中;{到通知之后Q再l箋q行?br /> 很多语言里面Q同步锁都由专门的对象表C,对象名通常叫Monitor?br /> 同样Q在很多语言中,信号量通常也有专门的对象名来表C,比如QMutexQSemphore?br /> 信号量模型要比同步锁模型复杂许多。一些系l中Q信号量甚至可以跨进E进行同步。另外一些信号量甚至q有计数功能Q能够控制同时运行的U程数?br /> 我们没有必要考虑那么复杂的模型。所有那些复杂的模型Q都是最基本的模型衍生出来的。只要掌握了(jin)最基本的信号量模型—?#8220;{待/通知”模型Q复杂模型也p刃而解?jin)?br /> 我们q是以Java语言Z。Java语言里面的同步锁和信号量概念都非常模p,没有专门的对象名词来表示同步锁和信号量,只有两个同步锁相关的关键字——volatile和synchronized?br /> q种模糊虽然D概念不清Q但同时也避免了(jin)Monitor、Mutex、Semphore{名词带来的U种误解。我们不必执着于名词之争,可以专注于理解实际的q行原理?br /> 在Java语言里面QQ何一个Object Reference都可以作为同步锁。同L(fng)道理QQ何一个Object Reference也可以作Z号量?br /> Object对象的wait()Ҏ(gu)是{待通知QObject对象的notify()Ҏ(gu)是发出通知?br /> 具体调用Ҏ(gu)?br /> Q?Q等待某个信号量的通知
public static final Object signal = new Object();

… f1() {
synchronized(singal) { // 首先我们要获取这个信号量。这个信号量同时也是一个同步锁

    // 只有成功获取?jin)signalq个信号量兼同步锁之后,我们才可能进入这D代?br />     signal.wait(); // q里要放弃信号量。本U程要进入signal信号量的待召QWaitingQ队?br />
// 可怜。辛辛苦苦争取到手的信号量,p么被攑ּ?br />
    // {到通知之后Q从待召QWaitingQ队列{到就l(ReadyQ队列里?br /> // 转到?jin)就l队列中Q离CPU核心(j)q了(jin)一步,有Z(x)l箋执行下面的代码了(jin)?br /> // 仍然需要把signal同步锁竞争到手,才能够真正l执行下面的代码。命苦啊?br />    
}
}

需要注意的是,上述代码中的signal.wait()的意思。signal.wait()很容易导致误解。signal.wait()的意思ƈ不是 _(d)signal开始waitQ而是_(d)q行q段代码的当前线E开始waitq个signal对象Q即q入signal对象的待召(WaitingQ队 列?br />
Q?Q发出某个信号量的通知
… f2() {
synchronized(singal) { // 首先Q我们同栯获取q个信号量。同时也是一个同步锁?br />
    // 只有成功获取?jin)signalq个信号量兼同步锁之后,我们才可能进入这D代?br /> signal.notify(); // q里Q我们通知signal的待召队列中的某个线E?br />
// 如果某个U程{到?jin)这个通知Q那个线E就?x){到就l队列中
// 但是本线E仍然l拥有signalq个同步锁,本线E仍然l执?br /> // 嘿嘿Q虽然本U程好心(j)通知其他U程Q?br /> // 但是Q本U程可没有那么高风亮节,攑ּ到手的同步锁
// 本线El执行下面的代码
   
}
}

需要注意的是,signal.notify()的意思。signal.notify()q不是通知signalq个对象本n。而是通知正在{待signal信号量的其他U程?br />
以上是Object的wait()和notify()的基本用法?br /> 实际上,wait()q可以定义等待时_(d)当线E在某信号量的待召队列中Q等到够长的时_(d)׃(x){无可等Q无需再等Q自己就从待召队列{UdqA队列中了(jin)?br /> 另外Q还有一个notifyAll()Ҏ(gu)Q表C通知待召队列里面的所有线E?br /> q些l节问题Qƈ不对大局产生影响?br />
l色U程

l色U程QGreen ThreadQ是一个相对于操作pȝU程QNative ThreadQ的概念?br /> 操作pȝU程QNative ThreadQ的意思就是,E序里面的线E会(x)真正映射到操作系l的U程Q线E的q行和调度都是由操作pȝ控制?br /> l色U程QGreen ThreadQ的意思是Q程序里面的U程不会(x)真正映射到操作系l的U程Q而是paq行q_自n来调度?br /> 当前版本的Python语言的线E就可以映射到操作系l线E。当前版本的Ruby语言的线E就属于l色U程Q无法映到操作pȝ的线E,因此Ruby语言的线E的q行速度比较慢?br /> N_(d)l色U程要比操作pȝU程要慢吗?当然不是q样。事实上Q情况可能正好相反。Ruby是一个特D的例子。线E调度器q不是很成熟?br /> 目前Q线E的行实现模型是l色U程。比如,stackless PythonQ就引入?jin)更加轻量的l色U程概念。在U程q发~程斚wQ无论是q行速度q是q发负蝲上,都优于Python?br /> 另一个更著名的例子就是ErLangQ爱立信公司开发的一U开源语aQ?br /> ErLang的绿色线E概念非常彻底。ErLang的线E不叫ThreadQ而是叫做Process。这很容易和q程hh。这里要注意区分一下?br /> ErLang Process之间Ҏ(gu)׃需要同步。因为ErLang语言的所有变量都是final的,不允许变量的值发生Q何变化。因此根本就不需要同步?br /> final变量的另一个好处就是,对象之间不可能出C叉引用,不可能构成一U环状的兌Q对象之间的兌都是单向的,?wi)状的。因此,内存垃圾回收的算法效率也非常高。这pErLang能够辑ֈSoft Real TimeQY实时Q的效果。这对于一门支持内存垃圑֛收的语言来说



]]>
just-in-time~译?/title><link>http://www.tkk7.com/tinysun/archive/2010/04/24/319257.html</link><dc:creator>何克?/dc:creator><author>何克?/author><pubDate>Sat, 24 Apr 2010 04:59:00 GMT</pubDate><guid>http://www.tkk7.com/tinysun/archive/2010/04/24/319257.html</guid><wfw:comment>http://www.tkk7.com/tinysun/comments/319257.html</wfw:comment><comments>http://www.tkk7.com/tinysun/archive/2010/04/24/319257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tinysun/comments/commentRss/319257.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tinysun/services/trackbacks/319257.html</trackback:ping><description><![CDATA[在Java和MS.net Framework中,Just-In-Time~译器所扮演的角色是一个中介者,负责代码译和安全检查的d?<br /> <br /> 在Java或C#{高U语a中,E序员编写的源代码首先被~译U某U格式的中间语言ILQIntermediate LanguageQ,IL是一U类似汇~语aQ与汇编不同的是QILq行的是在一个虚拟的机器环境中,或叫做虚拟机Q汇~语aq行在一个特定的机器q_中。虚拟机的好处ؓ(f)中间语言提供?jin)一个与q_无关的环境,比如java虚拟机,和CLRQCommon Language RuntimeQ,它能够根据所在的q_架构中间语a译中这个^C的机器语aQ从而完成程序的执行q程。担ȝ译Q务的是虚拟Z配备的JITQJust In TimeQ编译器。与传统~译器不同的是,JIT~译器是Ҏ(gu)行边解释Q只有需要执行的代码才被译成机器语aQ那些不?x)执行到代码被忽略掉的?<br /> <br /> JIT~译器担ȝW二Q务是(g)查代码的安全性。它必须保证~译出来的机器代码是安全Q即E序不会(x)非法讉K不属于本w的内存I间或者没有权限访问的I间Q这样可以防止恶意的E序修改敏感数据区域?<br /> <br /> 此外QJIT~译器提供了(jin)对代码优化的可选功能?<br /> <br /> 下图是Java应用E序的一个程序过E,JIT~译器是JVM的一个组成部分?<br /> <img src="http://by1.storage.msn.com/y1p9T_4JhVlirsb_XdqIhQDTexk7rCIBwg4p3xS66KZ7wPyRvIUtPkXfgQC2iTbFYxaHPTqO8qhYG6AwzvTRa53oOkeqOeJuwS1?PARTNER=WRITER" alt="" /> <br /> 参考资料:(x) <br /> [1] Microsoft MSDN, Compiling MSIL to Native code. <br /> [2] Simon Robinson, etc. Professional C# (2nd Edition). Wrox Press Inc, March 2002 <br /> [3] http://www.research.ibm.com/trl/projects/jit/index_e.htm <br /> <img src ="http://www.tkk7.com/tinysun/aggbug/319257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tinysun/" target="_blank">何克?/a> 2010-04-24 12:59 <a href="http://www.tkk7.com/tinysun/archive/2010/04/24/319257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>file的getPath getAbsolutePath和getCanonicalPath的不?/title><link>http://www.tkk7.com/tinysun/archive/2009/03/05/257941.html</link><dc:creator>何克?/dc:creator><author>何克?/author><pubDate>Thu, 05 Mar 2009 02:17:00 GMT</pubDate><guid>http://www.tkk7.com/tinysun/archive/2009/03/05/257941.html</guid><wfw:comment>http://www.tkk7.com/tinysun/comments/257941.html</wfw:comment><comments>http://www.tkk7.com/tinysun/archive/2009/03/05/257941.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tinysun/comments/commentRss/257941.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tinysun/services/trackbacks/257941.html</trackback:ping><description><![CDATA[<div id="bojzkzp" class="blog_content">file的这几个取得path的方法各有不同,下边说说详细的区?br /> <br /> 概念上的区别Q(内容来自jdkQ个人感觉这个描qC息,只能让明白的人明白,不明白的人看hq是有点隑ֺQ特别试中文版,英文版稍好些)所以在概念之后我会(x)举例说明。如果感觉看概念很篏pq直接看例子吧。看完例子回来看概念?x)好些?br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">getPath<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000"> String getPath()此抽象路径名{换ؓ(f)一个\径名字符丌Ӏ所得到的字W串使用默认名称分隔W来分隔名称序列中的名称?nbsp;<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />q回Q?br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />此抽象\径名的字W串形式<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /></span></div> <br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">getAbsolutePath<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000"> String getAbsolutePath()q回抽象路径名的l对路径名字W串?nbsp;<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />如果此抽象\径名已经是绝对\径名Q则q回该\径名字符Ԍq与 getPath() Ҏ(gu)一栗如果此抽象路径名是I的抽象路径名,则返回当前用L(fng)录的路径名字W串Q该目录ql属?nbsp;user.dir 指定。否则,使用与系l有关的方式分析此\径名。在 UNIX pȝ上,通过Ҏ(gu)当前用户目录分析某一相对路径名,可该\径名成ؓ(f)l对路径名。在 Microsoft Windows pȝ上,通过p\径名指定的当前驱动器目录Q如果有Q来分析某一相对路径名,可该\径名成ؓ(f)l对路径名;否则Q可以根据当前用L(fng)录来分析它?nbsp;<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />q回Q?br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />l对路径名字W串Q它与此抽象路径名表C相同的文g或目录的 <br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />抛出Q?nbsp;<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />SecurityException </span><span style="color: #000000">-</span><span style="color: #000000"> 如果无法讉K所需的系l属性倹{?br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />另请参见Q?br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />isAbsolute()<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /></span></div> <br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000"><span id="rrjmtgt" class="hilite1">getCanonicalPath</span><br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000"> String <span id="euurvxr" class="hilite1">getCanonicalPath</span>()<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />                        </span><span style="color: #0000ff">throws</span><span style="color: #000000"> IOExceptionq回抽象路径名的规范路径名字W串?nbsp;<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />规范路径名是l对路径名,q且是惟一的。规范\径名的准定义与pȝ有关。如有必要,此方法首先将路径名{换成l对路径名,q与调用 getAbsolutePath() Ҏ(gu)的效果一P然后用与pȝ相关的方式将它映到其惟一路径名。这通常涉及(qing)C路径名中U除多余的名Uͼ比如 </span><span style="color: #000000">"</span><span style="color: #000000">.</span><span style="color: #000000">"</span><span style="color: #000000"> ?nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..</span><span style="color: #000000">"</span><span style="color: #000000">Q、分析符可接(对于 UNIX q_Q,以及(qing)驱动器名{换成标准大小写Ş式(对于 Microsoft Windows q_Q?nbsp;<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />表示现有文g或目录的每个路径名都有一个惟一的规范Ş式。表C非存在文g或目录的每个路径名也有一个惟一的规范Ş式。非存在文g或目录\径名的规范Ş式可能不同于创徏文g或目录之后同一路径名的规范形式。同P现有文g或目录\径名的规范Ş式可能不同于删除文g或目录之后同一路径名的规范形式?nbsp;<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />q回Q?br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />表示与此抽象路径名相同的文g或目录的规范路径名字W串 <br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />抛出Q?nbsp;<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />IOException </span><span style="color: #000000">-</span><span style="color: #000000"> 如果发生 I</span><span style="color: #000000">/</span><span style="color: #000000">O 错误Q可能是因ؓ(f)构造规范\径名需要进行文件系l查询)(j) <br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />SecurityException </span><span style="color: #000000">-</span><span style="color: #000000"> 如果无法讉K所需的系l属性|或者存在安全管理器Q且?nbsp;SecurityManager.checkRead(java.io.FileDescriptor) Ҏ(gu)拒绝对该文gq行d讉K<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />从以下版本开始:(x) <br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />JDK1.</span><span style="color: #000000">1</span><span style="color: #000000"> <br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /></span></div> <br /> 二、例子:(x)<br /> 1QgetPath()与getAbsolutePath()的区?br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_26_412_Open_Image" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_26_412_Closed_Image" style="display: none" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">static</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> test1()</span><span id="Codehighlighter1_26_412_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.tkk7.com/Images/dot.gif" /></span><span id="Codehighlighter1_26_412_Open_Text"><span style="color: #000000">{<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        File file1 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">.\\test1.txt</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        File file2 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">D:\\workspace\\test\\test1.txt</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">-----默认相对路径Q取得\径不?-----</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file1.getPath());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file1.getAbsolutePath());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">-----默认l对路径:取得路径相同------</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file2.getPath());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file2.getAbsolutePath());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        <br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div> <br /> 得到的结果:(x)<br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">-----</span><span style="color: #000000">默认相对路径Q取得\径不?/span><span style="color: #000000">------</span><span style="color: #000000"><br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />.\test1.txt<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />D:\workspace\test\.\test1.txt<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">-----</span><span style="color: #000000">默认l对路径:取得路径相同</span><span style="color: #000000">------</span><span style="color: #000000"><br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />D:\workspace\test\test1.txt<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />D:\workspace\test\test1.txt</span></div> 因ؓ(f)getPath()得到的是构造file的时候的路径?br /> getAbsolutePath()得到的是全\?br /> 如果构造的时候就是全路径那直接返回全路径<br /> 如果构造的时候试相对路径Q返回当前目录的路径+构造file时候的路径<br /> <br /> 2QgetAbsolutePath()?span class="hilite1">getCanonicalPath</span>()的不?br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_43_189_Open_Image" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_43_189_Closed_Image" style="display: none" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">static</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> test2() </span><span style="color: #0000ff">throws</span><span style="color: #000000"> Exception</span><span id="Codehighlighter1_43_189_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.tkk7.com/Images/dot.gif" /></span><span id="Codehighlighter1_43_189_Open_Text"><span style="color: #000000">{<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        File file </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">..\\src\\test1.txt</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file.getAbsolutePath());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file.<span id="tnoejdq" class="hilite1">getCanonicalPath</span>());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div> 得到的结?br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">D:\workspace\test\..\src\test1.txt<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" />D:\workspace\src\test1.txt</span></div> 可以看到CanonicalPath不但是全路径Q而且?.或?q样的符可析出来?br /> 3,<span id="pghmnaj" class="hilite1">getCanonicalPath</span>()和自q不同?br /> 是解释q段?<br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">表示现有文g或目录的每个路径名都有一个惟一的规范Ş式。表C非存在文g或目录的每个路径名也有一个惟一的规范Ş式。非存在文g或目录\径名的规范Ş式可能不同于创徏文g或目录之后同一路径名的规范形式。同P现有文g或目录\径名的规范Ş式可能不同于删除文g或目录之后同一路径名的规范形式?nbsp;<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /></span></div> 单下边这D代码是看不到结果的Q要配合一定的操作来看。下Ҏ(gu)作步骤,同时讲解<br /> <br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_43_135_Open_Image" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_43_135_Closed_Image" style="display: none" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">static</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> test3() </span><span style="color: #0000ff">throws</span><span style="color: #000000"> Exception</span><span id="Codehighlighter1_43_135_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.tkk7.com/Images/dot.gif" /></span><span id="Codehighlighter1_43_135_Open_Text"><span style="color: #000000">{<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        File file </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">D:\\Text.txt</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file.<span id="mptfobz" class="hilite1">getCanonicalPath</span>());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div> 步骤Q?br /> 定你的pȝ是Windowspȝ?br /> (1),定D盘下没有Text.txtq个文gQ直接执行这D代码,得到的结果是:<br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">D:\Text.txt</span></div> 注意q里试大写的Text.txt<br /> (2)在D盘下建立一个文Ӟ名叫text.txtQ再ơ执行代码,得到l果<br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">D:\text.txt</span></div> 同样的代码得C同的l果?br /> 同时可以Ҏ(gu)getAbsolutePath()看看Q这个得到的l果是一L(fng)?br /> <br /> 原因Q?br /> window是大写不敏感的Q也是说在windows上test.txt和Test.txt是一个文Ӟ所以在windows上当文g不存在时Q得到的路径是按照输入的\径。但当文件存在时Q就?x)按照实际的情况来显C。这也就是徏立文件后和删除文件后?x)有不同的原因。文件夹和文件类伹{?br /> <br /> 三、最后:(x)<br /> 1Q尝试在linux下执行上边的步骤Q两ơ打印的l果是相同的Q因为linux是大写敏感的系l?br /> 2Q手动删掉test.txt,然后试执行下边代码<br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_43_287_Open_Image" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_43_287_Closed_Image" style="display: none" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">static</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> test4() </span><span style="color: #0000ff">throws</span><span style="color: #000000"> Exception</span><span id="Codehighlighter1_43_287_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.tkk7.com/Images/dot.gif" /></span><span id="Codehighlighter1_43_287_Open_Text"><span style="color: #000000">{<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        File file </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">D:\\Text.txt</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file.<span id="botydyh" class="hilite1">getCanonicalPath</span>());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        File file1 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">D:\\text.txt</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        file1.createNewFile();<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        file </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">D:\\Text.txt</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file.<span id="vefvavx" class="hilite1">getCanonicalPath</span>());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div> <br /> <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_43_203_Open_Image" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_43_203_Closed_Image" style="display: none" alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">static</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> test3() </span><span style="color: #0000ff">throws</span><span style="color: #000000"> Exception</span><span id="Codehighlighter1_43_203_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.tkk7.com/Images/dot.gif" /></span><span id="Codehighlighter1_43_203_Open_Text"><span style="color: #000000">{<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        File file1 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">D:\\text.txt</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        file1.createNewFile();<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        File file </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">D:\\Text.txt</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(file.<span id="omyzxke" class="hilite1">getCanonicalPath</span>());<br /> <img alt="" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span></div> 执行上边两个函数Q看看结果,然后思考一下ؓ(f)什么?<br /> 1,的结果是两个大写Q?br /> 2,的结果试两个写<br /> q箋两个大写的,是否跟上边的矛盾 Q?br /> q是因ؓ(f)虚拟机的~存机制造成的。第一ơFile file <span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> File(</span><span style="color: #000000">"</span><span style="color: #000000">D:\\Text.txt</span><span style="color: #000000">"</span><span style="color: #000000">);军_?jin)结?</span> <br /> <br /> 来至javaeye</div> <img src ="http://www.tkk7.com/tinysun/aggbug/257941.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tinysun/" target="_blank">何克?/a> 2009-03-05 10:17 <a href="http://www.tkk7.com/tinysun/archive/2009/03/05/257941.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>protected讉K权限http://www.tkk7.com/tinysun/archive/2009/02/21/255973.html何克?/dc:creator>何克?/author>Sat, 21 Feb 2009 11:39:00 GMThttp://www.tkk7.com/tinysun/archive/2009/02/21/255973.htmlhttp://www.tkk7.com/tinysun/comments/255973.htmlhttp://www.tkk7.com/tinysun/archive/2009/02/21/255973.html#Feedback0http://www.tkk7.com/tinysun/comments/commentRss/255973.htmlhttp://www.tkk7.com/tinysun/services/trackbacks/255973.html阅读全文

]]>
兌、组合、聚合、依赖关pL?/title><link>http://www.tkk7.com/tinysun/archive/2009/02/21/255957.html</link><dc:creator>何克?/dc:creator><author>何克?/author><pubDate>Sat, 21 Feb 2009 07:39:00 GMT</pubDate><guid>http://www.tkk7.com/tinysun/archive/2009/02/21/255957.html</guid><wfw:comment>http://www.tkk7.com/tinysun/comments/255957.html</wfw:comment><comments>http://www.tkk7.com/tinysun/archive/2009/02/21/255957.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tinysun/comments/commentRss/255957.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tinysun/services/trackbacks/255957.html</trackback:ping><description><![CDATA[<span style="font-family: 宋体">    cM间的关系</span><span style="font-family: 宋体">U类Q?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'"> Generalization(</span><span style="font-family: 宋体">泛化</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">Q?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Dependency(</span><span style="font-family: 宋体">依赖关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Association(</span><span style="font-family: 宋体">兌关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Aggregation(</span><span style="font-family: 宋体">聚合关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Composition(</span><span style="font-family: 宋体">合成关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">?br /> <span style="font-family: 宋体">    其中</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Aggregation(</span><span style="font-family: 宋体">聚合关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Composition(</span><span style="font-family: 宋体">合成关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">属于</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Association(</span><span style="font-family: 宋体">兌关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">Q是Ҏ(gu)?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Association</span><span style="font-family: 宋体">兌关系?span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Generalization(</span><span style="font-family: 宋体">泛化</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">表现为承或实现关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">(is a)</span><span style="font-family: 宋体">。具体Ş式ؓ(f)cMcM间的l承关系Q接口与接口之间的承关p,cd接口的实现关pR?br /> </span></span></span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'"><O:P> <div align="left"><img alt="" src="http://www.tkk7.com/images/blogjava_net/tinysun/isa.jpg" border="0" /><br />      <span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Association</span><span style="font-family: 宋体">兌 p表Cؓ(f)变量</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">(has a )</span><span style="font-family: 宋体">。类与类之间的联接,它一个类知道另一个类的属性和Ҏ(gu)。例如如?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">依赖?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">Q则</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">体现?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">的全局变量。关联关pL双向兌和单向关联。双向关联:(x)两个c都知道另一个类的公共属性和操作。单向关联:(x)只有一个类知道另外一个类的公共属性和操作。大多数兌应该是单向的Q单向关pLҎ(gu)建立和维护,有助于寻扑֏服用的类?br /> <br /> <img alt="" src="http://www.tkk7.com/images/blogjava_net/tinysun/association.jpg" border="0" /><br /> <br /> </span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">    Aggregat ion(</span><span style="font-family: 宋体">聚合关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">) </span><span style="font-family: 宋体">是关联关pȝ一U,是强的关联关pR聚合关pL整体和个体的关系。普通关联关pȝ两个cd于同一层次上,而聚合关pȝ两个cd于不同的层次Q一个是整体Q一个是部分。同Ӟ是一U弱?#8220;拥有”关系。体现的?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">对象可以包含</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">对象Q但</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">对象不是</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">对象的组成部分。具体表Cؓ(f)Q如?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">聚合成,表现?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">包含?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">的全局对象Q但?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">对象可以不在</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">创徏的时d建?br /> <br /> <img alt="" src="http://www.tkk7.com/images/blogjava_net/tinysun/aggregation.jpg" border="0" /><br /> <br /> </span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">    Composition(</span><span style="font-family: 宋体">l合关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">是关联关pȝ一U,是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Composition(</span><span style="font-family: 宋体">l合关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">是一U强?#8220;拥有”关系Q体C(jin)严格的部分和整体的关p,部分和整体的生命周期一致。如?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">l成Q表Cؓ(f)</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">包含?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">的全局对象Qƈ?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">对象?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">创徏的时d建?br /> <img alt="" src="http://www.tkk7.com/images/blogjava_net/tinysun/composition.jpg" border="0" /><br /> <br /> <span lang="EN-US" style="font-family: 'Verdana','sans-serif'">Dependency(</span><span style="font-family: 宋体">依赖关系</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">)</span><span style="font-family: 宋体">表现为函C的参?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">(use a)</span><span style="font-family: 宋体">。是cMcM间的q接Q表CZ个类依赖于另一个类的定义,其中一个类的变化将影响另外一个类。例如如?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">A</span><span style="font-family: 宋体">依赖?/span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">Q则</span><span lang="EN-US" style="font-family: 'Verdana','sans-serif'">B</span><span style="font-family: 宋体">体现为局部变量,Ҏ(gu)的参数、或?rn)态方法的调用?/span><br /> <br /> <img alt="" src="http://www.tkk7.com/images/blogjava_net/tinysun/dependency.jpg" border="0" /><br /> <br /> 来至?a target="_blank">http://blog.csdn.net/maybehelios/archive/2008/01/12/2038685.aspx</a> <br /> </span><br /> </div> </O:P></span> <img src ="http://www.tkk7.com/tinysun/aggbug/255957.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tinysun/" target="_blank">何克?/a> 2009-02-21 15:39 <a href="http://www.tkk7.com/tinysun/archive/2009/02/21/255957.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>比较分析Vector、ArrayList和hashtable hashmap数据l构http://www.tkk7.com/tinysun/archive/2009/02/19/255626.html何克?/dc:creator>何克?/author>Thu, 19 Feb 2009 10:43:00 GMThttp://www.tkk7.com/tinysun/archive/2009/02/19/255626.htmlhttp://www.tkk7.com/tinysun/comments/255626.htmlhttp://www.tkk7.com/tinysun/archive/2009/02/19/255626.html#Feedback0http://www.tkk7.com/tinysun/comments/commentRss/255626.htmlhttp://www.tkk7.com/tinysun/services/trackbacks/255626.html
U性表Q链表,哈希表是常用的数据结构,在进行Java开发时QJDK已经为我们提供了(jin)一pd相应的类来实现基本的数据l构。这些类均在java.util包中。本文试N过单的描述Q向读者阐q各个类的作用以?qing)如何正用这些类?

Collection
?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?#8220;子接?#8221;如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 />   除了(jin)hCollection接口必备的iterator()Ҏ(gu)外,Listq提供一个listIterator()Ҏ(gu)Q返回一个ListIterator接口Q和标准的Iterator接口相比QListIterator多了(jin)一些add()之类的方法,允许dQ删除,讑֮元素Q还能向前或向后遍历?br />   实现List接口的常用类有LinkedListQArrayListQVector和Stack?/p>

LinkedListc?/strong>
  LinkedList实现?jin)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实现?jin)可变大的数组。它允许所有元素,包括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改变了(jin)Vector的状态(例如Q添加或删除?jin)一些元素)(j)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)必须心(j)操作可变对象QMutable ObjectQ。如果一个Set中的可变元素改变?jin)自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(jin)旉和空间的均衡。增大load factor可以节省I间但相应的查找旉增大,q会(x)影响像get和putq样的操作?br /> 使用Hashtable的简单示例如下,?Q?Q?攑ֈHashtable中,他们的key分别?#8221;one”Q?#8221;two”Q?#8221;three”Q?br />     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要相当心(j)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实行“弱引?#8221;Q如果一个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>

同步?br /> Vector是同步的。这个类中的一些方法保证了(jin)Vector中的对象是线E安全的。而ArrayList则是异步的,因此ArrayList中的对象q不是线E安全的。因为同步的要求?x)?jing)响执行的效率Q所以如果你不需要线E安全的集合那么使用ArrayList是一个很好的选择Q这样可以避免由于同步带来的不必要的性能开销?br /> 数据增长
从内部实现机制来讲ArrayList?font size="+0">Vector
都是使用数组(Array)来控刉合中的对象。当你向q两U类型中增加元素的时候,如果元素的数目超Z(jin)内部数组目前的长度它们都需要扩展内部数l的长度Q?font size="+0">Vector
~省情况下自动增长原来一倍的数组长度QArrayList是原来的50%,所以最后你获得的这个集合所占的I间L比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因ؓ(f)你可以通过讄集合的初始化大小来避免不必要的资源开销?br /> 使用模式
在ArrayList?font size="+0">Vector
中,从一个指定的位置Q通过索引Q查找数据或是在集合的末֢加、移除一个元素所p的时间是一L(fng)Q这个时间我们用O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的旉?x)呈UŞ增长QO(n-i)Q其中n代表集合中元素的个数Qi代表元素增加或移除元素的索引位置。ؓ(f)什么会(x)q样呢?以ؓ(f)在进行上q操作的时候集合中Wi和第i个元素之后的所有元素都要执行位Uȝ操作。这一切意味着什么呢Q?br /> q意味着Q你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作Q你最好选择其他的集合操作类。比如,LinkList集合cd增加或移除集合中M位置的元素所p的时间都是一L(fng)?O(1)Q但它在索引一个元素的使用~比较慢QO(i),其中i是烦(ch)引的位置.使用ArrayList也很Ҏ(gu)Q因Z可以单的使用索引来代替创建iterator对象的操作。LinkList也会(x)为每个插入的元素创徏对象Q所有你要明白它也会(x)带来额外的开销?br /> 最后,在《Practical Java》一书中Peter Haggar使用一个简单的数组QArrayQ来代替Vector或ArrayList。尤其是对于执行效率要求高的E序更应如此。因Z用数l?Array)避免?jin)同步、额外的Ҏ(gu)调用和不必要的重新分配空间的操作?/p>

 

Vector?/span>Hashtable都是jdk1.0的就有了(jin)的。后来到java2后,java的容器框架改?/span>很多Q?/span>?/span>?jin)兼容,?/span>?/span>Vector?/span>Hashtable?/span>别实?/span>?jin)新的容器框架?/span>List?/span>Map?/span>ArrayList?/span>HashMap都是java2(也就?/span>jdk1.2)后才有的?/span>
1. 安全、效率方面:(x)如果?/span>实现?/span>?/span>安全Q?/span>?/span>要用Vector?/span>HashtableQ否则则?/span>ArrayList?/span>HashMapQ因?/span>ArrayList?/span>HashMap不?/span>?/span>?/span>?/span>安全?/span>问题Q所以效率要高些。但Collectionsc?/span>可以解决q?/span>?/span>问题?/span>
            Collections.synchronizedList
Collections.synchronizedMap
       2. ?/span>源方面:(x)当两者的定w?/span>满时Q它?/span>都会(x)?/span>?/span>?/span>?/span>其容量,?/span>Vector是按其容量的一倍增?/span>Q?/span>ArrayList?/span>按其定w?/span>50%增加Q所?/span>Vector更能?/span>?/span>?/span>源?/span>
          3.q代器:(x)Vector?/span>Hashtable使用EnumerationQ?/span>ArrayList?/span>HashMap使用Iterator
      ARRAY是必?/span>在声明的?/span>?/span>?/span>?/span>?/span>?/span>?/span>; ARRYLIST也是?/span>Vectorc?/span>?/span>,可以?/span>?/span>增加?/span>?/span>?/span>?/span>
        List?/span>Set的区?/span>Q?/span>
         List用来?/span>理序列,?/span>Set用来?/span>理集?/span>
         List中的内容可以?/span>?/span>Q?/span>Set?/span>不行?/span>
       VectorQ?/span>ArrayList?/span>HashtableQ?/span>HashMap的区别:(x)
               1.Vector?/span>ArrayList是数Dpd象。按照插入的序q行排列Q可以有重复倹{?/span>
               2.Hashtable?/span>HashMap是对象联pd象。按照自q排列方式q行排序Q不可以有重复倹{?/span>
     HashMapQ?/span>l?/span>承了(jin)Map接口Q?/span>实现?/span>Keys来存?/span>?/span>讉KValuesQKeys和Values都可?/span>?/span>I,它与Hashtablec?/span>的区?/span>在于Hashtablec?/span>?/span>Keys不能?/span>null,
     Vector内部实际是以Array实现的,也?/span>q?/span>元素的整数烦(ch)引来讉K元素Q但它只能存?/span>java.lang.Object?/span>象,不能用于存放基本c?/span>型数据,比如要存放一个整?/span>10,得用new Integer(10)构造出一?/span>Integer包装cd象再?/span>q?/span>厅R?/span>
q有一?
HASHMAP不是同步?U程不安全的,HASHTABLE是同步的,U程安全?   
在Hashtable中,所有涉?qing)到更新其中存放的内容的?gu)都是同步?nbsp;  
   如:(x)   
   public    synchronized    Object    put(Object    key,    Object    value)    {}   
   public    synchronized    Object    get(Object    key)    {}   
   ...   
    
   以此来保证Hashtable不会(x)被多个线E同时更?/div>
因ؓ(f)HashMap的公共方法上没加synchronized关键?/div>
如何理解synchronized   关键字呢?
比如:
用synchronized和不用synchronized单的说就?nbsp;  
   1个房子有2个门Q用synchronized的是从有锁的?nbsp;  
   q入房子Qƈ且进入后锁门Q出来后门打开?nbsp;  
   而不用synchronized的是从没有锁的门q入?nbsp;  
   从有锁的门进入的人只把q个门锁上,但没办法q预从无锁的门进入的?nbsp;  
   所以如果clear()Ҏ(gu)是synchronizedQ他q门后取走所有鸡?nbsp;  
   q时如果一个非synchronized的get()Ҏ(gu)惌门取得一个鸡蛋就出错?/div>


]]>[转]Java RPC通信机制之RMI http://www.tkk7.com/tinysun/archive/2008/11/15/240653.html何克?/dc:creator>何克?/author>Sat, 15 Nov 2008 03:24:00 GMThttp://www.tkk7.com/tinysun/archive/2008/11/15/240653.htmlhttp://www.tkk7.com/tinysun/comments/240653.htmlhttp://www.tkk7.com/tinysun/archive/2008/11/15/240653.html#Feedback0http://www.tkk7.com/tinysun/comments/commentRss/240653.htmlhttp://www.tkk7.com/tinysun/services/trackbacks/240653.html在传l的RPC~程接口逐渐淡出Z视线的同Ӟ新的、更便于使用且附加了(jin)更多Ҏ(gu)的RPC~程接口也不断涌玎ͼCORBA作ؓ(f)分布式对象计技术的典范Q在很长一D|间内极大地吸引了(jin)大家的注意,但是׃CORBA规范试图覆盖q多的内容,使得CORBA昑־q于复杂Q也极大地限制了(jin)CORBA的应用范_(d)本系列将向大家介l几U轻量的,更适于?/span>Java开发中使用?/span>RPC~程接口Q?/span>RMI?/span>XML-RPC?/span>SOAP?/span>

RMIQ?/span>Remote Method InvocationQ?/span>

与本pd介l的其它两种RPC~程接口不同Q?/span>RMIQ?/span>Remote Method InvocationQ显得有些老旧Q它是在Java-IDL加入J2SE之前被引入的?/span>RMI开发流E与CORBA如出一辙(从出现的旉上无法确?/span>RMI是否是按?/span>CORBA规范定制的)(j)Q因此,其开发过E相Ҏ(gu)较烦(ch)琐,但是׃RMI?/span>EJB的基Q因此,它在Java开发中h十分重要的地位?/span>

以下是创E方法调用的5个步骤:(x)

1.   定义一个扩展了(jin)Remote接口的接口,该接口中的每一个方法必d明它?yu)生一?/span>RemoteException异常Q?/span>

2.   定义一个实现该接口的类Q?/span>

3.   使用rmicE序生成q程实现所需的存根和框架Q?/span>

4.   创徏一个客L(fng)序和服务器进?/span>RMI调用Q?/span>

5.   启动rmiregistryq运行自q服务E序和客L(fng)序?/span>

下面举一个简单、而且被无数次引用的例子:(x)Echo?/span>

1、定?/span>Echo接口

//Echo.java

//The Echo remote interface

package demo.rmi;

import java.rmi.*;

public interface Echo extends Remote {

      String echo(String msg) throws RemoteException;

}

2、实?/span>Echo接口

//EchoServer.java

//The implementation of the Echo remote object

package demo.rmi;

import java.net.*;

import java.rmi.*;

import java.rmi.registry.*;

import java.rmi.server.*;

public class EchoServer

      extends UnicastRemoteObject

      implements Echo {

       //默认构g器,也要“?#8221;?/span>RemoteExceptionq例

      public EchoServer() throws RemoteException {

            super();

      }

      public String echo(String msg) throws RemoteException {

            return "Echo: " + msg;

      }

      public static void main(String [] args) {

            /*创徏和安装一个安全管理器Qo(h)其支?/span>RMI?/span>作ؓ(f)Java开发包的一部分Q适用?/span>RMI唯一一个是RMISecurityManager.*/

            System.setSecurityManager(new RMISecurityManager());

            try {

                     /*创徏q程对象的一个或多个实例Q下面是EchoServer对象*/

                  EchoServer es = new EchoServer();

                  /*?/span>RMIq程对象注册表注册至一个远E对象。一个远E对象拥有的Ҏ(gu)卛_生成指向其他q程对象的句柄,q样Q客户到注册表里讉K一ơ,得到W一个远E对象即?*/

                  Naming.rebind("EchoServer", es);

                  System.out.println("Ready to provide echo service...");

            } catch (Exception e) {

                  e.printStackTrace();

            }

      }

}

q个实现cM用了(jin)UnicastRemoteObject去连?/span>RMIpȝ。在我们的例子中Q我们是直接的从UnicastRemoteObjectq个cMl承的,事实上ƈ不一定要q样做,如果一个类不是?/span>UnicastRmeoteObject上承,那必M用它?/span>exportObject()Ҏ(gu)去连接到RMI。(否则Q运行时被告知无法序列化。)(j)

如果一个类l承?/span>UnicastRemoteObjectQ那么它必须提供一个构造函数ƈ且声明抛Z?/span>RemoteException对象Q否则,?x)遇到编译错误?j)。当q个构造函数调用了(jin)super()Q它?yu)激z?/span>UnicastRemoteObject中的代码完成RMI的连接和q程对象的初始化?/span>

3、运?/span>rmic~译实现c,产生_Stubc?/span>

?/span>demo.rmi.EchoServer.java上目录下运行如下命令:(x)

rmic demo.rmi.EchoServer

4、编写客L(fng)?/span>

//EchoClient.java

//Uses remote object EchoServer

package demo.rmi;

import java.rmi.*;

import java.rmi.registry.*;

public class EchoClient {

      public static void main(String [] args) {

            System.setSecurityManager(new RMISecurityManager());

            try {

                  Echo t = (Echo)Naming.lookup("EchoServer");

                  for (int i = 0; i < 10; i++) {

                        System.out.println(t.echo(String.valueOf(i)));

                  }

            } catch (Exception e) {

                  e.printStackTrace();

            }

      }

}

5、运?/span>

~码的工作就只有q些Q现在可以依ơ启?/span>rmiregistryQ启?/span>rmiregistry时可以附加一个端口,一般用默认的端口1099卛_Q这是默认的Naming Serviceq行端口Q?/span>EchoServer?/span>EchoClient?jin)。但是,虽然有些RMI的资料没有提刎ͼ但你q行时不可避免会(x)遇到如下两个错误Q?/span>

1Q?/span>java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:1099 connect,resolve)

原因很简单,RMI Server/ClientE序试图通过Socketq接讉K本机?/span>rmiregistry服务Q即RMI?/span>Naming ServiceQ其q行的默认端口是1099Q。要解决q个问题Q可以在q行Server/Client时指定一?/span>Policy文gQ关?/span>Policy的更多信息,见参?/span>2Q,如下Q?/span>

java -Djava.security.policy=demo/rmi/policyfile.txt demo.rmi.EchoServer

Policy文g的内容ؓ(f)Q?/span>

grant{

      permission java.net.SocketPermission "localhost:1099", "connect, resolve";

};

卛_许访问本机的1099端口?/span>

或者干脆来个彻底开放:(x)

grant {

      permission java.security.AllPermission "", "";

};

2Q?/span>java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:

        java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:

        java.lang.ClassNotFoundException: demo.rmi.EchoServer_Stub

        ...

如果你凑巧用启动rmiregistry的终端窗口启动了(jin)EchoServerQ那么你很走q,你看不到上面的错误,但如果你不是在看完这文章后再也用不到RMIQ那么,q个错误在那里等着你,:)?/span>

错误很明显,rmiregistry找不CEchoServer攑֜同一目录下的EchoServer_StubQ因?/span>package所?/span>demo.rmi目录的上U目录不?/span>rmiregistry?/span>classpath中,q个问题有两U解x案:(x)

aQ在启动rmiregistry前先调整一?/span>CLASSPATH环境变量Q以目录E:"ZQ执行:(x)

set CLASSPATH=%CLASSPATH%;E:"

bQ修?/span>codeQ在EchoServer中通过如下代码Q?/span>

Registry r = LocateRegistry.createRegistry(8111);

r.rebind("EchoServer", es);

在程序内部创Z?/span>LocateRegistryQƈ自w注册到?/span>LocateRegistryQ其中的数?/span>8111表示LocateRegistryq行的端口?/span>

同样Q对于客L(fng)序,也需要作相应的调_(d)(x)

Registry r = LocateRegistry.getRegistry("localhost", 8111);

Echo e = (Echo)r.lookup("EchoServer");

而不是像上面例子中一栯?/span>NamingstaticҎ(gu)来访问默认的rmiregistry服务?/span>

参考:(x)

1.      Java RMI Tutorial, http://www.ccs.neu.edu/home/kenb/com3337/rmi_tut.html

2.      Policy Tool - Policy File Creation and Management Tool. http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/policytool.html

3.     Java RMI入门实战Q?/span>http://www.huihoo.com/java/rmi/index.html


]]>
(?Java中URI,URL和URN的?/title><link>http://www.tkk7.com/tinysun/archive/2008/10/04/232297.html</link><dc:creator>何克?/dc:creator><author>何克?/author><pubDate>Sat, 04 Oct 2008 03:54:00 GMT</pubDate><guid>http://www.tkk7.com/tinysun/archive/2008/10/04/232297.html</guid><wfw:comment>http://www.tkk7.com/tinysun/comments/232297.html</wfw:comment><comments>http://www.tkk7.com/tinysun/archive/2008/10/04/232297.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tinysun/comments/commentRss/232297.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tinysun/services/trackbacks/232297.html</trackback:ping><description><![CDATA[     摘要: Java中URI,URL和URN的?从天极网抄录整理 2006-1-13 URI、URL和URN是识别、定位和命名|上资源的标准途径。本文分析了(jin)URI、URL和URN的概念,以及(qing)Java的URI和URLc(以及(qing)与URL相关的类Q,q演CZ(jin)如何在程序中使用q些cR? Internet被认为是全球的实际和抽象的资源的集合。实际的资源包括从文ӞfileQ到?person)Q抽象的资源包括...  <a href='http://www.tkk7.com/tinysun/archive/2008/10/04/232297.html'>阅读全文</a><img src ="http://www.tkk7.com/tinysun/aggbug/232297.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tinysun/" target="_blank">何克?/a> 2008-10-04 11:54 <a href="http://www.tkk7.com/tinysun/archive/2008/10/04/232297.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于javaq接sql server 2000的问?/title><link>http://www.tkk7.com/tinysun/archive/2008/03/10/185067.html</link><dc:creator>何克?/dc:creator><author>何克?/author><pubDate>Mon, 10 Mar 2008 06:15:00 GMT</pubDate><guid>http://www.tkk7.com/tinysun/archive/2008/03/10/185067.html</guid><wfw:comment>http://www.tkk7.com/tinysun/comments/185067.html</wfw:comment><comments>http://www.tkk7.com/tinysun/archive/2008/03/10/185067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tinysun/comments/commentRss/185067.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tinysun/services/trackbacks/185067.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt"> <p>在xp机器上面安装?jin)ms sql server2000?jdbcq接的时候出C(jin)各种问题.上网查询都解军_U录下来.</p> <p>1.</p> <p>[Microsoft][SQLServer 2000 Driver for JDBC]Error establishing socket.</p> <p>按照|上大家说的办法.打sp3的补?到官方网站上下蝲下来.安装文g以及(qing)版本相应的驱动jar?</p> <p>|址如下:http://www.microsoft.com/downloads/details.aspx?FamilyID=07287b11-0502-461a-b138-2aa54bfdc03a&DisplayLang=en</p> <p>注意: <font size="2">在安装升U包的时候要注意的是下蝲的安装文?setup.exe"仅仅是一ơ解压羃,在这个地方容易让Z为双d是安装了(jin).需?安装"一ơ后再到安装目录扑ֈsetup.bat文g执行安装.</font></p> <p><font size="2">同时也要自己所建工E下的lib包中用到的sqlserver驱动更换成sp3?</font></p> <p><font size="2">2.</font></p> <p>用户 'sa' dp|。原? 未与信Q SQL Server q接相关联?/p> <p>q一问题一般是׃SQL Server未集成Windowsw䆾验证D?br /> q个问题一般是׃sqlserver 没有集成windowsw䆾验证所D?W一步先打开SQL Server企业理器。选择服务器名UC右键选择“~辑SQL Server注册属?#8221;Q然后在对话框中选择“使用windowsw䆾验证”?br /> 如果q不?在执行第二步.W二? 同样右键Q选择“属?#8221;Q然后打开“安全?#8221;选项卡?nbsp;在选项卡中Q选择w䆾验证?#8220;SQL Server?Windows ”,其他不变. q样q个问题可以解?</p> <p>3.</p> <p>[SQLServer]对象名XXX无效</p> <p>q个一般是q陆数据库的用户名的权限造成的?/p> <p>我在做数据库q接的时候用户名用的是sa.之后换成?jin)自己徏的用P可以了(jin)。如果还不可以就l自己徏的用户重新分配一下权限?/p> <p> </p> <p>下面是我试的jsp代码?/p> <div id="vvheuht" class="highlighter"> <ol class="highlighter-j"> <li><span><%@ page contentType=</span><span id="hfvlqhy" class="string">"text/html; charset=gb2312"</span><span> language=</span><span id="vvhfrmo" class="string">"java"</span><span> </span> <li id="drauobz" class="alt"><span id="cughqzj" class="keyword">import</span><span>=</span><span id="wdijdfw" class="string">"java.sql.*"</span> <li><span id="ooafoqd" class="keyword">import</span><span>=</span><span id="miyhbdu" class="string">"java.io.*"</span> <li id="vcsxgbz" class="alt"><span id="lwxuoul" class="keyword">import</span><span>=</span><span id="alfglug" class="string">"java.sql.Connection"</span> <li><span id="ajvlmvx" class="keyword">import</span><span>=</span><span id="hwxchfs" class="string">"java.sql.Date"</span> <li id="bmrdecw" class="alt"><span id="krdtjsq" class="keyword">import</span><span>=</span><span id="ovtyzfh" class="string">"java.sql.PreparedStatement"</span> <li><span id="rnvlfdy" class="keyword">import</span><span>=</span><span id="gvhineg" class="string">"java.sql.ResultSet"</span> <li id="bbrlqoi" class="alt"><span id="rnhbyek" class="keyword">import</span><span>=</span><span id="gugwtre" class="string">"java.sql.SQLException"</span> <li><span id="mbnkeke" class="keyword">import</span><span>=</span><span id="gnotfsb" class="string">"java.sql.Statement"</span> <li id="ieugzmo" class="alt"><span>%></span> <li><span><html></span> <li id="lhkjkbo" class="alt"><span><body></span> <li><span>data from SQL SERVER DB:</span> <li id="hklfzfw" class="alt"><span><hr></span> <li><span><table></span> <li id="xebnoqo" class="alt"><span><%! String trans(String chi)</span> <li><span>{</span> <li id="labglvp" class="alt"><span>String result=</span><span id="hhxnhty" class="keyword">null</span><span>;</span> <li><span id="tabrlce" class="keyword">byte</span><span> temp[];</span> <li id="cukdegt" class="alt"><span id="wwqvpvb" class="keyword">try</span> <li><span>{</span> <li id="eaudxgp" class="alt"><span>temp=chi.getBytes(</span><span id="ehxrlgt" class="string">"iso-8859-1"</span><span>);</span> <li><span>result=</span><span id="yxchive" class="keyword">new</span><span> String(temp);</span> <li id="hstcwja" class="alt"><span>}</span> <li><span id="soabctc" class="keyword">catch</span><span>(UnsupportedEncodingException e)</span> <li id="ffvwqzi" class="alt"><span>{</span> <li><span>System.out.println(e.toString());</span> <li id="plicwyp" class="alt"><span>}</span> <li><span id="elbrwjw" class="keyword">return</span><span> result;</span> <li id="cghtjhf" class="alt"><span>} %></span> <li><span><%</span> <li id="qbnzwnw" class="alt"><span>Class.forName(</span><span id="cqgsikt" class="string">"com.microsoft.jdbc.sqlserver.SQLServerDriver"</span><span>).newInstance();</span> <li><span>Connection con=java.sql.DriverManager.getConnection(</span><span id="xiydxvi" class="string">"jdbc:microsoft:sqlserver://127.0.0.1:4567; DatabaseName=ch12"</span><span>,</span><span id="vvwmrto" class="string">"sx"</span><span>,</span><span id="wwmvarp" class="string">"sx"</span><span>);</span> <li id="mbvlqwc" class="alt"> <li><span>Statement stmt=con.createStatement();</span> <li id="njndafd" class="alt"><span>ResultSet rst=stmt.executeQuery(</span><span id="hzaqgtz" class="string">"select * from contact"</span><span>);</span> <li><span id="xtyoare" class="keyword">while</span><span> (rst.next())</span> <li id="vvpqvmo" class="alt"><span>{</span> <li><span>out.println(</span><span id="koejdya" class="string">"<tr>"</span><span>);</span> <li id="dklfrtv" class="alt"><span>out.println(</span><span id="ieukanp" class="string">"<td>"</span><span>+trans(rst.getString(</span><span id="soifviz" class="string">"userName"</span><span>))+</span><span id="kjsbkbz" class="string">"</td>"</span><span>);</span> <li><span>out.println(</span><span id="xpjstvx" class="string">"<td>"</span><span>+trans(rst.getString(</span><span id="bfqghfg" class="string">"phone"</span><span>))+</span><span id="peqrwuw" class="string">"</td>"</span><span>);</span> <li id="hdemvan" class="alt"><span>out.println(</span><span id="soauvxk" class="string">"<td>"</span><span>+trans(rst.getString(</span><span id="awefkxj" class="string">"mail"</span><span>))+</span><span id="fbrabou" class="string">"</td>"</span><span>);</span> <li><span>out.println(</span><span id="jqrpjek" class="string">"</tr>"</span><span>);</span> <li id="grlfzfh" class="alt"><span>}</span> <li><span>rst.close();</span> <li id="zztukik" class="alt"><span>stmt.close();</span> <li><span>con.close();</span> <li id="alqdbdq" class="alt"><span>%></span> <li><span></table></span> <li id="fifgdbs" class="alt"><span></body></span> <li><span></html></span></li> </ol> </div> <br /> 开发环?Eclipse3.3+Sql Server 2000<br /> 在练?fn)用Ibatis开发数据库应用E序?按照如下步骤:<br /> 1)<span style="font-family: 宋体">下蝲SQL Server 2000 driver for JDBC <br /> 2)安装驱动,q将msutil.jar,msbase.jar,mssqlserver.jard到classpath<br /> 3)写好配置文g,其中用了(jin)java property文g.<br /> //file:database.properties<br /> <font face="宋体">jdbc.driver=com.microsoft.jdbc.sqlserver.SQLServerDriver<br /> jdbc.url=jdbc:sqlserver://localhost:1433;DatabaseName=test;SelectMethod=cursor<br /> jdbc.username=sa<br /> jdbc.password=sa<br />     <br /> q行时却出现如下异常:<br /> <font face="宋体">ERROR - JakartaCommonsLoggingImpl.error(19) | SimpleDataSource: Error while loading properties.      <br /> Cause:  java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver<br /> java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver<br /> at java.net.URLClassLoader$1.run(URLClassLoader.java:200)<br /> at java.security.AccessController.doPrivileged(Native Method)<br /> at java.net.URLClassLoader.findClass(URLClassLoader.java:188)<br /> at java.lang.ClassLoader.loadClass(ClassLoader.java:306)<br /> at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)<br /> at java.lang.ClassLoader.loadClass(ClassLoader.java:251)<br /> at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)<br /> at java.lang.Class.forName0(Native Method)<br /> at java.lang.Class.forName(Class.java:164)<br /> at com.ibatis.common.resources.Resources.classForName(Resources.java:244)<br /> at com.ibatis.common.resources.Resources.instantiate(Resources.java:260)<br /> at com.ibatis.common.jdbc.SimpleDataSource.initialize(SimpleDataSource.java:199)<br /> at com.ibatis.common.jdbc.SimpleDataSource.<init>(SimpleDataSource.java:116)<br /> at com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory.initialize(SimpleDataSourceFactory.java:31)<br /> at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser$9.process(SqlMapConfigParser.java:318)<br /> at com.ibatis.common.xml.NodeletParser.processNodelet(NodeletParser.java:111)<br /> at com.ibatis.common.xml.NodeletParser.process(NodeletParser.java:95)<br /> at com.ibatis.common.xml.NodeletParser.process(NodeletParser.java:92)<br /> at com.ibatis.common.xml.NodeletParser.process(NodeletParser.java:92)<br /> at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:62)<br /> at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:50)<br /> at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser.parse(SqlMapConfigParser.java:81)<br /> at com.ibatis.sqlmap.client.SqlMapClientBuilder.buildSqlMapClient(SqlMapClientBuilder.java:62)<br /> at Ibatis.Test.<clinit>(Test.java:22)<br /> 最后在师兄帮助?下了(jin)SQL Server 2005的驱?l果成功?<br /> <br /> 事后仔细Ҏ(gu)?jin)SQL Server 2000 ?SQL Server 2005驱动包,惊奇的发?br /> <font face="宋体">com.microsoft.sqlserver.jdbc.SQLServerDriver  Q-Q->q个?000?br /> com.microsoft.jdbc.sqlserver.SQLServerDriver  -------->q个?005?br /> 真的汗死Q!<br /> </font></font></font></span></span> <img src ="http://www.tkk7.com/tinysun/aggbug/185067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tinysun/" target="_blank">何克?/a> 2008-03-10 14:15 <a href="http://www.tkk7.com/tinysun/archive/2008/03/10/185067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://milbolg.com" target="_blank">鶹˾Ʒ</a>| <a href="http://sewo66.com" target="_blank">޹һ߹ۿ</a>| <a href="http://fense1.com " target="_blank">޴߶ר</a>| <a href="http://bjbf99.com" target="_blank">޹˾þۺ</a>| <a href="http://saohuo7.com" target="_blank">ĻmvƵ</a>| <a href="http://www16am8.com" target="_blank">޾Ʒһþ</a>| <a href="http://d8139.com" target="_blank">ۺϾþһ</a>| <a href="http://51caox.com" target="_blank">Ƶ</a>| <a href="http://syeyo.com" target="_blank">ѹھƷþþþӰԺ</a>| <a href="http://zhuanjiao521.com" target="_blank">޹߶</a>| <a href="http://jogador1.com" target="_blank">þþþƷҹѲ</a>| <a href="http://chinashineway.com" target="_blank">߹ۿƬ</a>| <a href="http://18eeuus.com" target="_blank">Ļ</a>| <a href="http://jogador1.com" target="_blank">91ѹۿ</a>| <a href="http://my94ok.com" target="_blank">A޾VƷ</a>| <a href="http://u6u6u6.com" target="_blank">һƵ</a>| <a href="http://326h.com" target="_blank">Ʒ_ۿ</a>| <a href="http://hkcp168.com" target="_blank">ഺɫУ԰С˵</a>| <a href="http://sxhengshan.com" target="_blank">þƵ99</a>| <a href="http://yijiazhiwei.com" target="_blank">a vרav</a>| <a href="http://senimei9.com" target="_blank">ɫAV߹ۿ</a>| <a href="http://mosason.com" target="_blank">鶹¹AVԭ</a>| <a href="http://bz600.com" target="_blank">ŷպ</a>| <a href="http://www454yu.com" target="_blank">йƷһëƬѲ</a>| <a href="http://meiluniao.com" target="_blank">Ļ޹˾þþƷ</a>| <a href="http://www-070755.com" target="_blank">츾avҹ벻 </a>| <a href="http://www045888.com" target="_blank">ƵƷѹۿ99</a>| <a href="http://fholaer.com" target="_blank">һƷ</a>| <a href="http://kkm55.com" target="_blank">һ˿ѹۿձƵwww</a>| <a href="http://guoyit.com" target="_blank">ȾѾƷ</a>| <a href="http://323c.com" target="_blank">պһһ</a>| <a href="http://shzzhsy.com" target="_blank">999þþѾƷ</a>| <a href="http://0515bh.com" target="_blank">91vavava</a>| <a href="http://0755szyxcm.com" target="_blank">йavƬ</a>| <a href="http://caopropp.com" target="_blank">պƷһ</a>| <a href="http://8k91.com" target="_blank">½޾Ʒ</a>| <a href="http://xian66.com" target="_blank">ѹԺ߹ۿ</a>| <a href="http://998wc.com" target="_blank">Ů18һëƬѿ</a>| <a href="http://adcadm.com" target="_blank">һ߹ۿ</a>| <a href="http://www16am8.com" target="_blank">aר߹ۿɫ</a>| <a href="http://liuxilife.com" target="_blank">˹ۿëƬ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>