﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-少年阿宾-随笔分类-JavaMultithread</title><link>http://www.blogjava.net/stevenjohn/category/51101.html</link><description>那些青春的岁月</description><language>zh-cn</language><lastBuildDate>Sun, 28 Apr 2013 16:06:50 GMT</lastBuildDate><pubDate>Sun, 28 Apr 2013 16:06:50 GMT</pubDate><ttl>60</ttl><item><title>CyclicBarrier与CountDownLatch、栅栏与计数器</title><link>http://www.blogjava.net/stevenjohn/archive/2013/04/28/398548.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sun, 28 Apr 2013 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/04/28/398548.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/398548.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/04/28/398548.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/398548.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/398548.html</trackback:ping><description><![CDATA[在多线程设计中，我猜常常会遇到线程间相互等待以及某个线程等待1个或多个线程的场景，比如多线程精密计算和大量数据处理，这里写下我自己的体会和理解。 
<p>&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; 我想应该有很多办法，如果是简单的1：1关系，那么可以wait（）和notify（）解决，就像一把锁和一把钥匙；如果是1：N关系，这个1就需要关心N的所有状态了，最笨的办法是1可以去查看N当前的状态，轮询询问工作是否做完。而好点的办法是N做完后主动告诉1，<span style="color: #0000ff">然后N就会有2种选择，要么听从1的命令，要么继续干自己其他的活。</span></p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 用传统的方法我想应该是都能实现的，而JDK1.5提供了CyclicBarrier与CountDownLatch来解决了这两个问题，而她们的区别是：</p>
<p>&nbsp;&nbsp;&nbsp; CyclicBarrier使所有线程相互等待，而CountDownLatch使一个或多个线程等待其他线程。区别类似上面蓝色字体，CountDownLatch不会等待其他线程了，只要做完自己的工作就干自己的活去了，也就是run()方法里其他的任务。</p>
<p>&nbsp;</p>
<p>Example：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img id="Codehighlighter1_67_707_Open_Image" onclick="this.style.display='none'; Codehighlighter1_67_707_Open_Text.style.display='none'; Codehighlighter1_67_707_Closed_Image.style.display='inline'; Codehighlighter1_67_707_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_67_707_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_67_707_Closed_Text.style.display='none'; Codehighlighter1_67_707_Open_Image.style.display='inline'; Codehighlighter1_67_707_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif"><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;testCountDownLatch()&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;InterruptedException</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_67_707_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_67_707_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;CountDownLatch&nbsp;cdl</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CountDownLatch(</span><span style="color: #000000">2</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;ExecutorService&nbsp;exe</span><span style="color: #000000">=</span><span style="color: #000000">Executors.newFixedThreadPool(</span><span style="color: #000000">2</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;<br /><img id="Codehighlighter1_210_519_Open_Image" onclick="this.style.display='none'; Codehighlighter1_210_519_Open_Text.style.display='none'; Codehighlighter1_210_519_Closed_Image.style.display='inline'; Codehighlighter1_210_519_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_210_519_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_210_519_Closed_Text.style.display='none'; Codehighlighter1_210_519_Open_Image.style.display='inline'; Codehighlighter1_210_519_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Bow&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;&nbsp;Runnable</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_210_519_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_210_519_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;CountDownLatch&nbsp;cdl;&nbsp;&nbsp;&nbsp;<br /><img id="Codehighlighter1_276_307_Open_Image" onclick="this.style.display='none'; Codehighlighter1_276_307_Open_Text.style.display='none'; Codehighlighter1_276_307_Closed_Image.style.display='inline'; Codehighlighter1_276_307_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_276_307_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_276_307_Closed_Text.style.display='none'; Codehighlighter1_276_307_Open_Image.style.display='inline'; Codehighlighter1_276_307_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Bow(CountDownLatch&nbsp;cdl)</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_276_307_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_276_307_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.cdl</span><span style="color: #000000">=</span><span style="color: #000000">cdl;&nbsp;&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br /><img id="Codehighlighter1_333_511_Open_Image" onclick="this.style.display='none'; Codehighlighter1_333_511_Open_Text.style.display='none'; Codehighlighter1_333_511_Closed_Image.style.display='inline'; Codehighlighter1_333_511_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_333_511_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_333_511_Closed_Text.style.display='none'; Codehighlighter1_333_511_Open_Image.style.display='inline'; Codehighlighter1_333_511_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;run()</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_333_511_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_333_511_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">The&nbsp;bow&nbsp;is&nbsp;coming</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">kick&nbsp;a&nbsp;bow&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.cdl.countDown();&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">do&nbsp;other&nbsp;thing</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;exe.execute(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Bow(cdl));&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;exe.execute(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Bow(cdl));&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;exe.shutdown();&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">Wait<img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;cdl.await();&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">End..</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" />&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />&nbsp;&nbsp;<br /><img id="Codehighlighter1_758_885_Open_Image" onclick="this.style.display='none'; Codehighlighter1_758_885_Open_Text.style.display='none'; Codehighlighter1_758_885_Closed_Image.style.display='inline'; Codehighlighter1_758_885_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_758_885_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_758_885_Closed_Text.style.display='none'; Codehighlighter1_758_885_Open_Image.style.display='inline'; Codehighlighter1_758_885_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_758_885_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_758_885_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br /><img id="Codehighlighter1_775_830_Open_Image" onclick="this.style.display='none'; Codehighlighter1_775_830_Open_Text.style.display='none'; Codehighlighter1_775_830_Closed_Image.style.display='inline'; Codehighlighter1_775_830_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_775_830_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_775_830_Closed_Text.style.display='none'; Codehighlighter1_775_830_Open_Image.style.display='inline'; Codehighlighter1_775_830_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_775_830_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_775_830_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Test.testCountDownLatch();&nbsp;&nbsp;&nbsp;<br /><img id="Codehighlighter1_863_876_Open_Image" onclick="this.style.display='none'; Codehighlighter1_863_876_Open_Text.style.display='none'; Codehighlighter1_863_876_Closed_Image.style.display='inline'; Codehighlighter1_863_876_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_863_876_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_863_876_Closed_Text.style.display='none'; Codehighlighter1_863_876_Open_Image.style.display='inline'; Codehighlighter1_863_876_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(InterruptedException&nbsp;e)&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_863_876_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_863_876_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span></div>
<p>&nbsp;</p>
<p>输出的结果为：</p>
<p>&nbsp;</p>
<p>The bow is coming<br />kick a bow <br /><span style="color: #0000ff">do other thing</span><br />Wait...<br />The bow is coming<br />kick a bow <br /><span style="color: #0000ff">do other thing</span><br />End..</p>
<p>&nbsp;</p>
<p>如上所说do other thing不受影响。</p>
<p>&nbsp;</p>
<p>写了一个CyclicBarrier的例子：</p>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img id="Codehighlighter1_90_903_Open_Image" onclick="this.style.display='none'; Codehighlighter1_90_903_Open_Text.style.display='none'; Codehighlighter1_90_903_Closed_Image.style.display='inline'; Codehighlighter1_90_903_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_90_903_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_90_903_Closed_Text.style.display='none'; Codehighlighter1_90_903_Open_Image.style.display='inline'; Codehighlighter1_90_903_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif"><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;testCyclicBarrier()&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;InterruptedException,&nbsp;BrokenBarrierException</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_90_903_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_90_903_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CyclicBarrier&nbsp;barr</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CyclicBarrier(</span><span style="color: #000000">2</span><span style="color: #000000">+</span><span style="color: #000000">1</span><span style="color: #000000">);<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExecutorService&nbsp;exe</span><span style="color: #000000">=</span><span style="color: #000000">Executors.newFixedThreadPool(</span><span style="color: #000000">2</span><span style="color: #000000">);<br /><img id="Codehighlighter1_231_738_Open_Image" onclick="this.style.display='none'; Codehighlighter1_231_738_Open_Text.style.display='none'; Codehighlighter1_231_738_Closed_Image.style.display='inline'; Codehighlighter1_231_738_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_231_738_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_231_738_Closed_Text.style.display='none'; Codehighlighter1_231_738_Open_Image.style.display='inline'; Codehighlighter1_231_738_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Bow&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;&nbsp;Runnable</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_231_738_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_231_738_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CyclicBarrier&nbsp;barr;<br /><img id="Codehighlighter1_291_318_Open_Image" onclick="this.style.display='none'; Codehighlighter1_291_318_Open_Text.style.display='none'; Codehighlighter1_291_318_Closed_Image.style.display='inline'; Codehighlighter1_291_318_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_291_318_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_291_318_Closed_Text.style.display='none'; Codehighlighter1_291_318_Open_Image.style.display='inline'; Codehighlighter1_291_318_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Bow(CyclicBarrier&nbsp;barr)</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_291_318_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_291_318_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.barr</span><span style="color: #000000">=</span><span style="color: #000000">barr;&nbsp;&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /><img id="Codehighlighter1_341_733_Open_Image" onclick="this.style.display='none'; Codehighlighter1_341_733_Open_Text.style.display='none'; Codehighlighter1_341_733_Closed_Image.style.display='inline'; Codehighlighter1_341_733_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_341_733_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_341_733_Closed_Text.style.display='none'; Codehighlighter1_341_733_Open_Image.style.display='inline'; Codehighlighter1_341_733_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;run()</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_341_733_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_341_733_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">The&nbsp;bow&nbsp;is&nbsp;coming</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">kick&nbsp;a&nbsp;down</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img id="Codehighlighter1_438_465_Open_Image" onclick="this.style.display='none'; Codehighlighter1_438_465_Open_Text.style.display='none'; Codehighlighter1_438_465_Closed_Image.style.display='inline'; Codehighlighter1_438_465_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_438_465_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_438_465_Closed_Text.style.display='none'; Codehighlighter1_438_465_Open_Image.style.display='inline'; Codehighlighter1_438_465_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_438_465_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_438_465_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;barr.await();<br /><img id="Codehighlighter1_498_573_Open_Image" onclick="this.style.display='none'; Codehighlighter1_498_573_Open_Text.style.display='none'; Codehighlighter1_498_573_Closed_Image.style.display='inline'; Codehighlighter1_498_573_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_498_573_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_498_573_Closed_Text.style.display='none'; Codehighlighter1_498_573_Open_Image.style.display='inline'; Codehighlighter1_498_573_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(InterruptedException&nbsp;e)&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_498_573_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_498_573_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;TODO&nbsp;Auto-generated&nbsp;catch&nbsp;block</span><span style="color: #008000"><br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br /><img id="Codehighlighter1_608_683_Open_Image" onclick="this.style.display='none'; Codehighlighter1_608_683_Open_Text.style.display='none'; Codehighlighter1_608_683_Closed_Image.style.display='inline'; Codehighlighter1_608_683_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_608_683_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_608_683_Closed_Text.style.display='none'; Codehighlighter1_608_683_Open_Image.style.display='inline'; Codehighlighter1_608_683_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(BrokenBarrierException&nbsp;e)&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_608_683_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_608_683_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;TODO&nbsp;Auto-generated&nbsp;catch&nbsp;block</span><span style="color: #008000"><br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">do&nbsp;other&nbsp;thing</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exe.execute(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Bow(barr));<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exe.execute(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Bow(barr));<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exe.shutdown();<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">Wait<img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;barr.await();<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">End..</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br /><img id="Codehighlighter1_947_1069_Open_Image" onclick="this.style.display='none'; Codehighlighter1_947_1069_Open_Text.style.display='none'; Codehighlighter1_947_1069_Closed_Image.style.display='inline'; Codehighlighter1_947_1069_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_947_1069_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_947_1069_Closed_Text.style.display='none'; Codehighlighter1_947_1069_Open_Image.style.display='inline'; Codehighlighter1_947_1069_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_947_1069_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_947_1069_Open_Text"><span style="color: #000000">{<br /><img id="Codehighlighter1_955_988_Open_Image" onclick="this.style.display='none'; Codehighlighter1_955_988_Open_Text.style.display='none'; Codehighlighter1_955_988_Closed_Image.style.display='inline'; Codehighlighter1_955_988_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_955_988_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_955_988_Closed_Text.style.display='none'; Codehighlighter1_955_988_Open_Image.style.display='inline'; Codehighlighter1_955_988_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_955_988_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_955_988_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Test.testCyclicBarrier();<br /><img id="Codehighlighter1_1021_1025_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1021_1025_Open_Text.style.display='none'; Codehighlighter1_1021_1025_Closed_Image.style.display='inline'; Codehighlighter1_1021_1025_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_1021_1025_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_1021_1025_Closed_Text.style.display='none'; Codehighlighter1_1021_1025_Open_Image.style.display='inline'; Codehighlighter1_1021_1025_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(InterruptedException&nbsp;e)&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_1021_1025_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_1021_1025_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /><img id="Codehighlighter1_1062_1066_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1062_1066_Open_Text.style.display='none'; Codehighlighter1_1062_1066_Closed_Image.style.display='inline'; Codehighlighter1_1062_1066_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="display: none" id="Codehighlighter1_1062_1066_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_1062_1066_Closed_Text.style.display='none'; Codehighlighter1_1062_1066_Open_Image.style.display='inline'; Codehighlighter1_1062_1066_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(BrokenBarrierException&nbsp;e)&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_1062_1066_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_1062_1066_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<p>&nbsp;</p>
<p>输出结果为：</p>
<p>&nbsp;</p>
<p>Wait...<br />The bow is coming<br />kick a down<br />The bow is coming<br />kick a down<br /><span style="color: #0000ff">do other thing</span><br />End..<br /><span style="color: #0000ff">do other thing</span></p>
<p>&nbsp;</p>
<p><strong><span style="color: #ff6600">总结：</span></strong></p>
<p>我们看到do other thing被阻塞了，直到最后才执行，可见，栅栏和计数器的目完全不同了。向Doug Lea牛人学习：）</p>
<p>&nbsp;<br /><br /><br /><br /><br /><br /><br /><br /><br /><br />在网上看到很多人对于CountDownLatch和CyclicBarrier的区别简单理解为CountDownLatch是一次性的，而CyclicBarrier在调用reset之后还可以继续使用。那如果只是这么简单的话，我觉得CyclicBarrier简单命名为<strong>ResetableCountDownLatch</strong>好了，显然不是的。<br />我的理解是，要从他们的设计目的去看这两个类。javadoc里面的描述是这样的。 </p>
<blockquote>
<p>CountDownLatch: A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.</p>
<p>CyclicBarrier : A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.</p></blockquote>
<p>可能是我的英语不够好吧， 我感觉从这个javadoc里面要准确理解他们的差异还是不容易的。<br />我的理解是</p>
<p>CountDownLatch : <strong>一个线程</strong>(或者多个)， 等待另外<strong>N个线程</strong>完成<strong>某个事情</strong>之后才能执行。 &nbsp; CyclicBarrier &nbsp; &nbsp; &nbsp; &nbsp;: <strong>N个线程</strong>相互等待，任何一个线程完成之前，所有的线程都必须等待。<br />这样应该就清楚一点了，对于CountDownLatch来说，重点是那个<strong>&#8220;一个线程&#8221;</strong>, 是它在等待， 而另外那N的线程在把<strong>&#8220;某个事情&#8221;</strong>做完之后可以继续等待，可以终止。而对于CyclicBarrier来说，重点是那<strong>N个线程</strong>，他们之间任何一个没有完成，所有的线程都必须等待。</p>
<p><!-- .entry-content --></p><br /><br />
<p>CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.<br />而CyclicBarrier更像一个水闸, 线程执行就想水流, 在水闸处都会堵住, 等到水满(线程到齐)了, 才开始泄流.</p><img src ="http://www.blogjava.net/stevenjohn/aggbug/398548.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-04-28 15:37 <a href="http://www.blogjava.net/stevenjohn/archive/2013/04/28/398548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Object之wait,notify,notifyAll </title><link>http://www.blogjava.net/stevenjohn/archive/2013/01/16/394330.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Wed, 16 Jan 2013 15:46:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/01/16/394330.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/394330.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/01/16/394330.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/394330.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/394330.html</trackback:ping><description><![CDATA[&nbsp;Java所有的类都具有线程的潜力，Java赋予的每个对象一个锁，在计算机内部工作在同一时间，只有一个对象可以持有锁，也就是说程序在同一时间只有一个程序可以运行，这里我把对象比作是一个小的程序。而多处理器，那么就另当别论了。 
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这里我们首先学习一下公共方法wait,notify,notifyAll。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait方法可以使在当前线程的对象等待，直到别的线程调用此对象的notify或notifyAll方法（注意：调用的是此对象的notify和notifyAll），并且当前运行的线程必须具有此对象的对象监视器</p>
<p>package com.abin.lee.thread.thread;</p>
<p>public class CarryTask extends Thread {<br />&nbsp;public void run() { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (this) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t = Thread.currentThread(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(t.getId() + t.getName() + ":task start, wait for notify..."); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.wait(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(t.getId() + t.getName() + ":task continue..."); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException ex) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(CarryTask.class.getName()); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; } </p>
<p><br />}<br /></p><br /><br /><br /><br />
<p>package com.abin.lee.thread.thread;</p>
<p>public class CarryWait {<br />&nbsp;public static void main(String[] args) throws InterruptedException {<br />&nbsp;&nbsp;CarryTask task = new CarryTask();<br />&nbsp;&nbsp;Thread t = Thread.currentThread();<br />&nbsp;&nbsp;System.out.println(t.getId() + t.getName() + ":task start...");<br />&nbsp;&nbsp;task.start();<br />&nbsp;&nbsp;Thread.sleep(2000);<br />&nbsp;&nbsp;synchronized (task) {<br />&nbsp;&nbsp;&nbsp;System.out.println("id="+Thread.currentThread().getId()+",Name="+Thread.currentThread().getName()+",task="+task+",notify");<br />&nbsp;&nbsp;&nbsp;task.notify();<br />&nbsp;&nbsp;}<br />&nbsp;}</p>
<p>}<br /></p><br /><br /><br /><br /><a href="http://www.iteye.com/topic/1124814">http://www.iteye.com/topic/1124814</a><br /><img src ="http://www.blogjava.net/stevenjohn/aggbug/394330.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-01-16 23:46 <a href="http://www.blogjava.net/stevenjohn/archive/2013/01/16/394330.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Future FutureTask</title><link>http://www.blogjava.net/stevenjohn/archive/2013/01/10/394071.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 10 Jan 2013 06:17:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/01/10/394071.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/394071.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/01/10/394071.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/394071.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/394071.html</trackback:ping><description><![CDATA[<div>//实例一，这里面用到了信号量Semaphore和FutureTask<br />
<p>package net.abin.lee.mythread.callable;</p>
<p>import java.util.concurrent.Callable;<br />import java.util.concurrent.Semaphore;<br />import java.util.concurrent.locks.Lock;<br />import java.util.concurrent.locks.ReentrantReadWriteLock;</p>
<p>public class FutureGo implements Callable&lt;String&gt; {<br />&nbsp;private String message;<br />&nbsp;private static final Semaphore semaphore=new Semaphore(3);<br />&nbsp;private final ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();<br />&nbsp;public FutureGo(String message) {<br />&nbsp;&nbsp;this.message = message;<br />&nbsp;}</p>
<p>&nbsp;public String call() throws InterruptedException {<br />&nbsp;&nbsp;semaphore.acquire();<br />&nbsp;&nbsp;Lock read=rwl.readLock();<br />&nbsp;&nbsp;Lock write=rwl.readLock();<br />&nbsp;&nbsp;read.lock();&nbsp;&nbsp;<br />&nbsp;&nbsp;System.out.println("message"+message+",Name"+Thread.currentThread().getName()+"进来了");<br />&nbsp;&nbsp;read.unlock();<br />&nbsp;&nbsp;write.lock();<br />&nbsp;&nbsp;String result=message+"你好!";<br />&nbsp;&nbsp;Thread.sleep(1000);<br />&nbsp;&nbsp;System.out.println("message"+message+"Name"+Thread.currentThread().getName()+"离开了");<br />&nbsp;&nbsp;write.unlock();<br />&nbsp;&nbsp;semaphore.release();<br />&nbsp;&nbsp;return result;<br />&nbsp;}<br />}<br /><br /><br /><br />//FutureTaskTest.java<br /></p>
<p>package net.abin.lee.mythread.callable;</p>
<p>import java.util.concurrent.Callable;<br />import java.util.concurrent.ExecutionException;<br />import java.util.concurrent.ExecutorService;<br />import java.util.concurrent.Executors;<br />import java.util.concurrent.FutureTask;</p>
<p>public class FutureTaskTest {<br />&nbsp;public static void main(String[] args) throws InterruptedException,<br />&nbsp;&nbsp;&nbsp;ExecutionException {<br />&nbsp;&nbsp;Callable&lt;String&gt; go = new FutureGo("abin");<br />&nbsp;&nbsp;FutureTask&lt;String&gt; task = new FutureTask&lt;String&gt;(go);<br />&nbsp;&nbsp;ExecutorService executor = Executors.newCachedThreadPool();<br />&nbsp;&nbsp;if (!executor.isShutdown()) {<br />&nbsp;&nbsp;&nbsp;executor.execute(task);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;String result = "";<br />&nbsp;&nbsp;if (!task.isDone()) {<br />&nbsp;&nbsp;&nbsp;result = (String) task.get();<br />&nbsp;&nbsp;&nbsp;System.out.println("result=" + result);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp; executor.shutdown();<br />&nbsp;}</p>
<p>}<br /></p>
<p><br /><br /><br /><br /><br />//实例一，这里面用到了信号量Semaphore和FutureTask<br /><br /></p></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/394071.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-01-10 14:17 <a href="http://www.blogjava.net/stevenjohn/archive/2013/01/10/394071.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java线程并发库学习--CyclicBarrier</title><link>http://www.blogjava.net/stevenjohn/archive/2013/01/08/393933.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Mon, 07 Jan 2013 16:39:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/01/08/393933.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/393933.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/01/08/393933.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/393933.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/393933.html</trackback:ping><description><![CDATA[<!--StartFragment -->

<div>public&nbsp;class&nbsp;CyclicBarrier<br />extends&nbsp;Object<br />一个同步辅助类，它允许一组线程互相等待，直到到达某个公共屏障点&nbsp;(common&nbsp;barrier&nbsp;point)。在涉及一组固定大小的线程的程序中，这些线程必须不时地互相等待，此时&nbsp;CyclicBarrier&nbsp;很有用。因为该&nbsp;barrier&nbsp;在释放等待线程后可以重用，所以称它为循环&nbsp;的&nbsp;barrier。<br />CyclicBarrier&nbsp;支持一个可选的&nbsp;Runnable&nbsp;命令，在一组线程中的最后一个线程到达之后（但在释放所有线程之前），该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态，此屏障操作&nbsp;很有用。<br />以上是jdk文档的说明<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;现在说说我们今天活动的内容、首先我们要在公司大厅集合、然后参观陈云故居<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;参观完后集合、准备去淀水湖参观。（有3辆车、对应3个线程）<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;我们必须等大家都到齐了才能去下个地方、比如说&nbsp;、在公司集合、3辆车子都到了才能出发<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;要不然人装不下啊。这是我们可以用到java线程并发库的CyclicBarrier类<br />&nbsp;<br />public&nbsp;class&nbsp;CyclicBarrierTest&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;CyclicBarrier&nbsp;cb&nbsp;=&nbsp;new&nbsp;CyclicBarrier(3);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//final&nbsp;Semaphore&nbsp;semaphore=new&nbsp;Semaphore(1);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;&lt;=&nbsp;3;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;Thread(new&nbsp;Runnable()&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//semaphore.acquire();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;"公司大厅集合");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;"公司大厅等待....");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//semaphore.release();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cb.await();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(2000);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//semaphore.acquire();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;"陈云故居集合");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;"陈云故居等待....");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//semaphore.release();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cb.await();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(2000);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//semaphore.acquire();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;"淀水湖集合");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;"淀水湖等待....准备回家了");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//semaphore.release();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cb.await();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(2000);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(InterruptedException&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(BrokenBarrierException&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}).start();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br />以下是输出结果：<br />Thread-0公司大厅集合<br />Thread-0公司大厅等待....<br />Thread-2公司大厅集合<br />Thread-1公司大厅集合<br />Thread-1公司大厅等待....<br />Thread-2公司大厅等待....<br />Thread-0陈云故居集合<br />Thread-1陈云故居集合<br />Thread-2陈云故居集合<br />Thread-1陈云故居等待....<br />Thread-0陈云故居等待....<br />Thread-2陈云故居等待....<br />Thread-0淀水湖集合<br />Thread-2淀水湖集合<br />Thread-1淀水湖集合<br />Thread-2淀水湖等待....准备回家了<br />Thread-0淀水湖等待....准备回家了<br />Thread-1淀水湖等待....准备回家了<br /><br />***注意上述代码中的Semaphore类、它也是java线程并发库中的一个类、更多具体作用我们以后再探讨。<br />以下是使用Semaphore后的输出结果：（相信你已经知道不同的地方了）<br />Thread-0公司大厅集合<br />Thread-0公司大厅等待....<br />Thread-1公司大厅集合<br />Thread-1公司大厅等待....<br />Thread-2公司大厅集合<br />Thread-2公司大厅等待....<br />Thread-2陈云故居集合<br />Thread-2陈云故居等待....<br />Thread-1陈云故居集合<br />Thread-1陈云故居等待....<br />Thread-0陈云故居集合<br />Thread-0陈云故居等待....<br />Thread-2淀水湖集合<br />Thread-2淀水湖等待....准备回家了<br />Thread-1淀水湖集合<br />Thread-1淀水湖等待....准备回家了<br />Thread-0淀水湖集合<br />Thread-0淀水湖等待....准备回家了<br /><br /><a href="http://blog.sina.com.cn/s/blog_7f448c520101219g.html">http://blog.sina.com.cn/s/blog_7f448c520101219g.html</a></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/393933.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-01-08 00:39 <a href="http://www.blogjava.net/stevenjohn/archive/2013/01/08/393933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java线程并发库学习--Exchanger</title><link>http://www.blogjava.net/stevenjohn/archive/2013/01/08/393932.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Mon, 07 Jan 2013 16:35:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/01/08/393932.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/393932.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/01/08/393932.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/393932.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/393932.html</trackback:ping><description><![CDATA[<!--StartFragment -->


<div>public&nbsp;class&nbsp;Exchanger&lt;V&gt;<br />extends&nbsp;Object<br />可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给&nbsp;exchange&nbsp;方法，与伙伴线程进行匹配，并且在返回时接收其伙伴的对象。Exchanger&nbsp;可能被视为&nbsp;SynchronousQueue&nbsp;的双向形式。Exchanger&nbsp;可能在应用程序（比如遗传算法和管道设计）中很有用。<br /><br />以上是jdk文档的说明。<br /><br />&nbsp;&nbsp;*&nbsp;今天公司党委组织活动、12点半call我电话、我以80码的速度狂奔过去、上了一个车子（A车）、<br />&nbsp;&nbsp;*&nbsp;戴着眼镜四处瞄了下，没发现什么美女啊。假寐了一会儿，司机说另外一个车子（B车）上要换过来<br />&nbsp;&nbsp;*&nbsp;一个人、让车子上的人下去一个去B车。由于地势原因、我就下去了。<br />&nbsp;&nbsp;*<br />&nbsp;&nbsp;*&nbsp;一路上突然想到了java线程并发库中的Exchanger类。A车我们可以看作是一个线程、B车我们也可以<br />&nbsp;&nbsp;*&nbsp;看作是一个线程，我和B车上的一位美女换位子，就可以用到Exchanger类的exchange方法。<br />&nbsp;&nbsp;*<br />&nbsp;&nbsp;*&nbsp;代码如下：<br /><br />public&nbsp;class&nbsp;ExchangerTest&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;Exchanger&lt;String&gt;&nbsp;exchange=new&nbsp;Exchanger&lt;String&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//final&nbsp;String&nbsp;a="yupan";<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//final&nbsp;String&nbsp;b="a&nbsp;girl";<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;String[]&nbsp;carA=new&nbsp;String[]{"zhangsan","lisi","yupan"};<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;String[]&nbsp;carB=new&nbsp;String[]{"meinv_a","meinv_b","meinv_c"};<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//A车线程<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;Thread(new&nbsp;Runnable(){<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;carA_copy=carA;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("交换前：A车上的第三位乘客："+carA[2]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;carA_copy[2]=exchange.exchange(carA_copy[2]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("交换后：A车上的第三位乘客："+carA[2]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(InterruptedException&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}).start();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//B车线程<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;Thread(new&nbsp;Runnable(){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;carB_copy=carB;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("交换前：B车上的第三位乘客："+carB[2]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;carB_copy[2]=exchange.exchange(carB_copy[2]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("交换后：B车上的第三位乘客："+carB[2]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(InterruptedException&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}).start();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br />输出结果：<br /><br />交换前：A车上的第三位乘客：yupan<br />交换前：B车上的第三位乘客：meinv_c<br />交换后：B车上的第三位乘客：yupan<br />交换后：A车上的第三位乘客：meinv_c<br /><br /><a href="http://blog.sina.com.cn/s/blog_7f448c5201012183.html">http://blog.sina.com.cn/s/blog_7f448c5201012183.html</a></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/393932.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-01-08 00:35 <a href="http://www.blogjava.net/stevenjohn/archive/2013/01/08/393932.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 信号量 Semaphore 介绍 </title><link>http://www.blogjava.net/stevenjohn/archive/2013/01/08/393930.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Mon, 07 Jan 2013 16:11:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/01/08/393930.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/393930.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/01/08/393930.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/393930.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/393930.html</trackback:ping><description><![CDATA[<strong><font color="#aa00ff">Semaphore</font></strong><span>当前在多线程环境下被扩放使用，</span>操作系统的信号量是个很重要的概念，在进程控制方面都有应用。Java 并发库 的Semaphore 可以很轻松完成信号量控制，Semaphore可以控制某个资源可被同时访问的个数，通过&nbsp;<span style="color: #ff0000">acquire()</span>&nbsp;获取一个许可，如果没有就等待，而 <span style="color: #ff0000">release()</span>&nbsp;释放一个许可。比如在Windows下可以设置共享文件的最大客户端访问个数。&nbsp; 
<p>Semaphore实现的功能就类似厕所有5个坑，假如有10个人要上厕所，那么同时只能有多少个人去上厕所呢？同时只能有5个人能够占用，当5个人中 的任何一个人让开后，其中等待的另外5个人中又有一个人可以占用了。另外等待的5个人中可以是随机获得优先机会，也可以是按照先来后到的顺序获得机会，这取决于构造Semaphore对象时传入的参数选项。单个信号量的Semaphore对象可以实现互斥锁的功能，并且可以是由一个线程获得了&#8220;锁&#8221;，再由另一个线程释放&#8220;锁&#8221;，这可应用于死锁恢复的一些场合。<br /><br />Semaphore维护了当前访问的个数，提供同步机制，控制同时访问的个数。在数据结构中链表可以保存&#8220;无限&#8221;的节点，用Semaphore可以实现有限大小的链表。另外重入锁 ReentrantLock&nbsp;也可以实现该功能，但实现上要复杂些。&nbsp;</p>
<p>下面的Demo中申明了一个只有5个许可的Semaphore，而有20个线程要访问这个资源，通过acquire()和release()获取和释放访问许可。</p>
<p><span style="color: #3b5900">package com.test;</span></p>
<p><span style="color: #3b5900">import java.util.concurrent.ExecutorService;</span></p>
<p><span style="color: #3b5900">import java.util.concurrent.Executors;</span></p>
<p><span style="color: #3b5900">import java.util.concurrent.Semaphore;</span></p>
<p><span style="color: #3b5900">public class TestSemaphore {</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public static void main(String[] args) {</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000">&nbsp;// 线程池</span></span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ExecutorService exec = Executors.newCachedThreadPool();</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #ff0000">// 只能5个线程同时访问</span></span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final Semaphore semp = new Semaphore(5);</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000">&nbsp;// 模拟20个客户端访问</span></span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for (int index = 0; index &lt; 20; index++) {</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final int NO = index;</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;Runnable run = new Runnable() {</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;public void run() {</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;try {</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #ff0000">// 获取许可</span></span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #5500ff">semp.acquire();</span></span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;System.out.println("Accessing: " + NO);</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread.sleep((long) (Math.random() * 10000));</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #ff0000">// 访问完后，释放</span></span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0055ff">semp.release();</span></span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;System.out.println("-----------------"+semp.availablePermits());</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (InterruptedException e) {</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;}</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;}</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;};</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exec.execute(run);</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; }</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000">&nbsp;// 退出线程池</span></span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;exec.shutdown();</span></p>
<p><span style="color: #3b5900">&nbsp; &nbsp; &nbsp; &nbsp;}</span></p>
<p><span style="color: #3b5900">}&nbsp;</span></p>
<p><span style="color: #3b5900">执行结果如下：</span></p>
<p><span style="color: #ff0000">Accessing: 0</span></p>
<p><span style="color: #ff0000">Accessing: 1</span></p>
<p><span style="color: #ff0000">Accessing: 3</span></p>
<p><span style="color: #ff0000">Accessing: 4</span></p>
<p><span style="color: #ff0000">Accessing: 2</span></p>
<p><span style="color: #ff0000">-----------------0</span></p>
<p><span style="color: #ff0000">Accessing: 6</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 7</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 8</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 10</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 9</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 5</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 12</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 11</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 13</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 14</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 15</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 16</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 17</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 18</span></p>
<p><span style="color: #ff0000">-----------------1</span></p>
<p><span style="color: #ff0000">Accessing: 19</span></p><br /><br /><br /><a href="http://www.cnblogs.com/whgw/archive/2011/09/29/2195555.html">http://www.cnblogs.com/whgw/archive/2011/09/29/2195555.html</a><img src ="http://www.blogjava.net/stevenjohn/aggbug/393930.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-01-08 00:11 <a href="http://www.blogjava.net/stevenjohn/archive/2013/01/08/393930.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java并发包中的几种ExecutorService</title><link>http://www.blogjava.net/stevenjohn/archive/2012/12/19/393203.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Wed, 19 Dec 2012 04:39:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/12/19/393203.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/393203.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/12/19/393203.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/393203.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/393203.html</trackback:ping><description><![CDATA[<p style="font-size: medium">&nbsp;1.CachedThreadPool</p>
<p style="font-size: medium">&nbsp; &nbsp; CachedThreadPool首先会按照需要创建足够多的线程来执行任务(Task)。随着程序执行的过程，有的线程执行完了任务，可以被重新循环使用时，才不再创建新的线程来执行任务。我们采用《Thinking In Java》中的例子来分析。</p>
<p style="font-size: medium">&nbsp; &nbsp; 首先，任务定义如下(实现了Runnable接口，并且复写了run方法)：</p>
<p style="font-size: medium"></p>package net.jerryblog.concurrent; <br />public class LiftOff implements Runnable{ <br />&nbsp;&nbsp;&nbsp; protected int countDown = 10; //Default <br />&nbsp;&nbsp;&nbsp; private static int taskCount = 0; <br />&nbsp;&nbsp;&nbsp; private final int id = taskCount++;&nbsp; <br />&nbsp;&nbsp;&nbsp; public LiftOff() {} <br />&nbsp;&nbsp;&nbsp; public LiftOff(int countDown) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.countDown = countDown; <br />&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; public String status() { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "#" + id + "(" + <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (countDown &gt; 0 ? countDown : "LiftOff!") + ") "; <br />&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; @Override <br />&nbsp;&nbsp;&nbsp; public void run() { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(countDown-- &gt; 0) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.print(status()); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.yield(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />} <br /><br />采用CachedThreadPool方式执行编写的客户端程序如下：&nbsp;<br /><br /><br />package net.jerryblog.concurrent; <br />import java.util.concurrent.ExecutorService; <br />import java.util.concurrent.Executors; <br />public class CachedThreadPool { <br />&nbsp;&nbsp;&nbsp; public static void main(String[] args) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ExecutorService exec = Executors.newCachedThreadPool(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; 10; i++) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exec.execute(new LiftOff()); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exec.shutdown();&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; } <br />} <br /><br />上面的程序中，有10个任务，采用CachedThreadPool模式，exec没遇到一个LiftOff的对象(Task)，就会创建一个线程来处理任务。现在假设遇到到第4个任务时，之前用于处理第一个任务的线程已经执行完成任务了，那么不会创建新的线程来处理任务，而是使用之前处理第一个任务的线程来处理这第4个任务。接着如果遇到第5个任务时，前面那些任务都还没有执行完，那么就会又新创建线程来执行第5个任务。否则，使用之前执行完任务的线程来处理新的任务。 
<p style="font-size: medium">2.FixedThreadPool</p>
<p style="font-size: medium">&nbsp; &nbsp;&nbsp;&nbsp;FixedThreadPool模式会使用一个优先固定数目的线程来处理若干数目的任务。规定数目的线程处理所有任务，一旦有线程处理完了任务就会被用来处理新的任务(如果有的话)。这种模式与上面的CachedThreadPool是不同的，CachedThreadPool模式下处理一定数量的任务的线程数目是不确定的。而FixedThreadPool模式下<span style="color: #ff0000">最多</span> 的线程数目是一定的。</p>
<p style="font-size: medium">&nbsp; &nbsp; 采用FixedThreadPool模式编写客户端程序如下：</p><br />package net.jerryblog.concurrent; <br />import java.util.concurrent.ExecutorService; <br />import java.util.concurrent.Executors; <br />public class FixedThreadPool { <br />&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //三个线程来执行五个任务 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ExecutorService exec = Executors.newFixedThreadPool(3);&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; 5; i++) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exec.execute(new LiftOff()); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exec.shutdown(); <br />&nbsp;&nbsp;&nbsp; } <br />} <br /><br />
<p>3.SingleThreadExecutor模式</p>
<p>&nbsp; &nbsp; SingleThreadExecutor模式只会创建一个线程。它和FixedThreadPool比较类似，不过线程数是一个。如果多个任务被提交给SingleThreadExecutor的话，那么这些任务会被保存在一个队列中，并且会按照任务提交的顺序，一个先执行完成再执行另外一个线程。</p>
<p>&nbsp; &nbsp; SingleThreadExecutor模式可以保证只有一个任务会被执行。这种特点可以被用来处理共享资源的问题而不需要考虑同步的问题。</p>
<p>&nbsp; &nbsp; SingleThreadExecutor模式编写的客户端程序如下：&nbsp; </p><br /><br />package net.jerryblog.concurrent; <br />import java.util.concurrent.ExecutorService; <br />import java.util.concurrent.Executors; <br />public class SingleThreadExecutor { <br />&nbsp;&nbsp;&nbsp; public static void main(String[] args) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ExecutorService exec = Executors.newSingleThreadExecutor(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 2; i++) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exec.execute(new LiftOff()); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; } <br />} <br /><br />这种模式下执行的结果如下：<br />#0(9) #0(8) #0(7) #0(6) #0(5) #0(4) #0(3) #0(2) #0(1) #0(LiftOff!)<br />#1(9) #1(8) #1(7) #1(6) #1(5) #1(4) #1(3) #1(2) #1(1) #1(LiftOff!) <br />第一个任务执行完了之后才开始执行第二个任务。<span style="font-size: 12px">&nbsp;</span>&nbsp;&nbsp;<br /><br /><br /><br /><br /><img src ="http://www.blogjava.net/stevenjohn/aggbug/393203.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-12-19 12:39 <a href="http://www.blogjava.net/stevenjohn/archive/2012/12/19/393203.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java多线程 返回结果</title><link>http://www.blogjava.net/stevenjohn/archive/2012/12/07/392585.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Fri, 07 Dec 2012 02:36:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/12/07/392585.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/392585.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/12/07/392585.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/392585.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/392585.html</trackback:ping><description><![CDATA[方法一：<br />
<p>package com.abin.lee.thread;</p>
<p>import java.util.Iterator;<br />import java.util.LinkedList;<br />import java.util.List;<br />public class ThreadSync{<br />&nbsp;<br />&nbsp;public static List&lt;Object&gt; ThreadSync(final String message) throws InterruptedException{<br />&nbsp;&nbsp;final List&lt;Object&gt; list=new LinkedList&lt;Object&gt;();<br />&nbsp;&nbsp;Thread thread=new Thread(){<br />&nbsp;&nbsp;&nbsp;public void run(){<br />&nbsp;&nbsp;&nbsp;&nbsp;if(message.equals("one")){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(0, message);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;};<br />&nbsp;&nbsp;thread.start();<br />&nbsp;&nbsp;thread.join();<br />&nbsp;&nbsp;return list;<br />&nbsp;}<br />&nbsp;<br />&nbsp;public static void main(String[] args) throws InterruptedException {<br />&nbsp;&nbsp;List&lt;Object&gt; list=ThreadSync("one1");<br />&nbsp;&nbsp;System.out.println("size="+list.size());<br />&nbsp;&nbsp;for(Iterator it=list.iterator();it.hasNext();){<br />&nbsp;&nbsp;&nbsp;Object obj=(Object)it.next();<br />&nbsp;&nbsp;&nbsp;System.out.println("obj="+obj);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;<br />&nbsp;}<br />}<br /><br /><br /><br /><br />方法二：<br /></p><img src ="http://www.blogjava.net/stevenjohn/aggbug/392585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-12-07 10:36 <a href="http://www.blogjava.net/stevenjohn/archive/2012/12/07/392585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何快速处理十万条数据到数据库</title><link>http://www.blogjava.net/stevenjohn/archive/2012/12/05/392451.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Tue, 04 Dec 2012 16:54:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/12/05/392451.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/392451.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/12/05/392451.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/392451.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/392451.html</trackback:ping><description><![CDATA[<div>如何快速处理十万条数据到数据库</div><img src ="http://www.blogjava.net/stevenjohn/aggbug/392451.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-12-05 00:54 <a href="http://www.blogjava.net/stevenjohn/archive/2012/12/05/392451.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java主线程唤醒子线程的疑问</title><link>http://www.blogjava.net/stevenjohn/archive/2012/11/17/391484.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Fri, 16 Nov 2012 17:38:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/11/17/391484.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/391484.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/11/17/391484.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/391484.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/391484.html</trackback:ping><description><![CDATA[<!--StartFragment -->


<div>public&nbsp;class&nbsp;Example{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[]){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;target=new&nbsp;A();&nbsp;&nbsp;&nbsp;&nbsp;//线程thread的目标对象&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;thread=new&nbsp;Thread(target);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread.setName("张三");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread.start();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(target.getStop()==false){}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("我是主线程,负责恢复"+thread.getName()+"线程");&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.restart();&nbsp;&nbsp;//恢复thread线程<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}&nbsp;<br />class&nbsp;A&nbsp;implements&nbsp;Runnable{<br />&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;number=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;boolean&nbsp;stop=false;<br />&nbsp;&nbsp;&nbsp;&nbsp;boolean&nbsp;getStop(){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;stop;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run(){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(true){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()+"的number="+number);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(number==3){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try{&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()+"被挂起");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stop=true;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hangUP();//挂起线程<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()+"恢复执行");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch(Exception&nbsp;e){}&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try{&nbsp;Thread.sleep(1000);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch(Exception&nbsp;e){}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;synchronized&nbsp;void&nbsp;&nbsp;hangUP()&nbsp;throws&nbsp;InterruptedException{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;synchronized&nbsp;void&nbsp;&nbsp;restart(){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;notifyAll();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /><br /><br /><br /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/24px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; -webkit-text-decorations-in-effect: none" class="Apple-style-span">求教，main方法中的空循环是做什么用的？初学线程，不是很理解。</span><br /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/24px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; -webkit-text-decorations-in-effect: none" class="Apple-style-span">while(target.getStop()==false){}<br />等待target线程结束，target线程运行在主线程main里面，如果没有这个空循环，主线程顺序执行，target还没有执行完得时候主线程已经执行完退出了，会导致target也退出。</span></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/391484.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-11-17 01:38 <a href="http://www.blogjava.net/stevenjohn/archive/2012/11/17/391484.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java wait()与notify()</title><link>http://www.blogjava.net/stevenjohn/archive/2012/11/17/391483.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Fri, 16 Nov 2012 17:01:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/11/17/391483.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/391483.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/11/17/391483.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/391483.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/391483.html</trackback:ping><description><![CDATA[<span style="padding: 0px; margin: 0px; color: #2c2c2c; line-height: 28px; text-indent: 28px; background-color: #ffffff; font-family: 宋体; ">下面的例子通过</span><span style="padding: 0px; margin: 0px; color: #2c2c2c; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; text-indent: 28px; background-color: #ffffff; ">wait()</span><span style="padding: 0px; margin: 0px; color: #2c2c2c; line-height: 28px; text-indent: 28px; background-color: #ffffff; font-family: 宋体; ">来取代忙等待机制，当收到通知消息时，</span><span style="padding: 0px; margin: 0px; color: #2c2c2c; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; text-indent: 28px; background-color: #ffffff; ">notify</span><span style="padding: 0px; margin: 0px; color: #2c2c2c; line-height: 28px; text-indent: 28px; background-color: #ffffff; font-family: 宋体; ">当前</span><span style="padding: 0px; margin: 0px; color: #2c2c2c; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; text-indent: 28px; background-color: #ffffff; ">Monitor</span><span style="padding: 0px; margin: 0px; color: #2c2c2c; line-height: 28px; text-indent: 28px; background-color: #ffffff; font-family: 宋体; ">类线程。</span>&nbsp;<br /><div></div><div>package com.abin.lee.servlet.mythread.runnable;</div><div></div><div>import java.util.concurrent.TimeUnit;</div><div></div><div>public class MyObject implements Runnable{</div><div><span style="white-space:pre">	</span>private Monitor monitor;</div><div><span style="white-space:pre">	</span>public MyObject(Monitor monitor) {</div><div><span style="white-space:pre">		</span>this.monitor=monitor;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public void run(){</div><div><span style="white-space:pre">		</span>try {</div><div><span style="white-space:pre">			</span>System.out.println("beforeTimeUnit.SECONDS="+System.currentTimeMillis());</div><div><span style="white-space:pre">			</span>TimeUnit.SECONDS.sleep(3);</div><div><span style="white-space:pre">			</span>System.out.println("i am going");</div><div><span style="white-space:pre">			</span>monitor.getMessage();</div><div><span style="white-space:pre">		</span>} catch (InterruptedException e) {</div><div><span style="white-space:pre">			</span>e.printStackTrace();</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">	</span>}</div><div>}</div><div><br /><br /><br /><br /><div>package com.abin.lee.servlet.mythread.runnable;</div><div></div><div>public class Monitor implements Runnable{</div><div><span style="white-space:pre">	</span>private volatile boolean go=false;</div><div><span style="white-space:pre">	</span>public synchronized void getMessage(){</div><div><span style="white-space:pre">		</span>System.out.println("beforenotify getMessage="+System.currentTimeMillis());</div><div><span style="white-space:pre">		</span>go=true;</div><div><span style="white-space:pre">		</span>notify();</div><div><span style="white-space:pre">		</span>System.out.println("afternotify getMessage="+System.currentTimeMillis());</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public synchronized void watching() throws InterruptedException{</div><div><span style="white-space:pre">		</span>System.out.println("beforewait watching="+System.currentTimeMillis());</div><div><span style="white-space:pre">		</span>while(go==false)</div><div><span style="white-space:pre">			</span>wait();</div><div><span style="white-space:pre">		</span>System.out.println("he has gone");</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public void run(){</div><div><span style="white-space:pre">		</span>try {</div><div><span style="white-space:pre">			</span>watching();</div><div><span style="white-space:pre">		</span>} catch (InterruptedException e) {</div><div><span style="white-space:pre">			</span>e.printStackTrace();</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">	</span>}</div><div>}</div><div><br /><br /><br /><br /><br /><div>package com.abin.lee.servlet.mythread.runnable;</div><div></div><div>public class Wait {</div><div><span style="white-space:pre">	</span>public static void main(String[] args) {</div><div><span style="white-space:pre">		</span>Monitor monitor=new Monitor();</div><div><span style="white-space:pre">		</span>MyObject obj=new MyObject(monitor);</div><div><span style="white-space:pre">		</span>new Thread(obj).start();</div><div><span style="white-space:pre">		</span>new Thread(monitor).start();</div><div><span style="white-space:pre">	</span>}</div><div>}</div><div></div></div></div><div><div><div style="margin: 0px; color: #2c2c2c; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff; "><span style="padding: 0px; margin: 0px; font-size: 10pt; font-family: 'Courier New'; color: black; "></span></div></div><div></div></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/391483.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-11-17 01:01 <a href="http://www.blogjava.net/stevenjohn/archive/2012/11/17/391483.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中是不是父线程阻塞后子线程就无法继续执行？</title><link>http://www.blogjava.net/stevenjohn/archive/2012/11/16/391480.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Fri, 16 Nov 2012 13:43:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/11/16/391480.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/391480.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/11/16/391480.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/391480.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/391480.html</trackback:ping><description><![CDATA[<span class="mod-title ml-5" accuse="qTitle">Java中是不是父线程阻塞后子线程就无法继续执行？</span> <pre class="line q-content mt-10" accuse="qContent">如果不是，该如何实现阻塞父线程但继续执行子线程？</pre><pre class="line q-content mt-10" accuse="qContent"><span class="mod-title ml-5" accuse="qTitle"><pre id="best-content-992515643" class="best-text mb-10" accuse="aContent">不是，这个问题属于线程调度。<br />让一个线程明确的给另外一个线程运行机会，采用以下方法：<br />1.调整线程优先级<br />2.让处于运行状态的线程调用Thread.sleep（）方法<br />3.让处于运行状态的线程调用Thread.yield（）方法<br />4.让处于运行状态的线程调用另外一个线程的jion（）方法</pre></span></pre><img src ="http://www.blogjava.net/stevenjohn/aggbug/391480.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-11-16 21:43 <a href="http://www.blogjava.net/stevenjohn/archive/2012/11/16/391480.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程题目 </title><link>http://www.blogjava.net/stevenjohn/archive/2012/11/09/391119.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Fri, 09 Nov 2012 13:37:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/11/09/391119.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/391119.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/11/09/391119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/391119.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/391119.html</trackback:ping><description><![CDATA[<ol><li><span>看到一个题目：针对下面的程序，写出magic方法&nbsp;让整个程序只打印出step1,step2&nbsp;不打印step3&nbsp;&nbsp;</span></li></ol><br />&nbsp;&nbsp;&nbsp; public static void enter(Object obj) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Step 1");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />&nbsp;&nbsp;&nbsp;magic1(obj);<br />&nbsp;&nbsp;} catch (Exception e) {<br />&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Step 2");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (obj) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Step 3 (never reached here)");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }
<p>&nbsp;题目的意思很容易理解，可是要做出这道题目需要对多线程的基本改进非常的理解。</p>
<p>下面列出基本思路：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>主线程想获取<span style="font-size: 10pt">obj</span>的锁，但是获取不到，说明子线程始终在占据着这个对象的锁。</p>
<p>同时主线程又能返回。</p>
<p>那现在就要实现让子线程先跑，然后再唤醒主线程。这个显然是锁的占有和唤醒，那么问题来了，将什么做为这个锁呢？如果是<span style="font-size: 10pt">obj</span>的话，不可能，因为子线程显然不能在放掉<span style="font-size: 10pt">obj.</span></p>
<p>那么只能是子线程自己的锁。</p>
<p>&nbsp;</p>
<p>下边是程序</p>&nbsp;&nbsp;&nbsp; static void magic1(final Object obj) throws Exception{<br />&nbsp;&nbsp;&nbsp; &nbsp;final Thread t = new Thread(){<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;public void run(){<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;synchronized(this){<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;synchronized(obj){<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;notify();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;join();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp; &nbsp;};<br />&nbsp;&nbsp;&nbsp; &nbsp;synchronized(t){<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;t.start();<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;t.wait();<br />&nbsp;&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp;&nbsp; }<br /><br /><br /><br /><br /><img src ="http://www.blogjava.net/stevenjohn/aggbug/391119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-11-09 21:37 <a href="http://www.blogjava.net/stevenjohn/archive/2012/11/09/391119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 多线程1加到100</title><link>http://www.blogjava.net/stevenjohn/archive/2012/11/05/390843.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Mon, 05 Nov 2012 14:40:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/11/05/390843.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/390843.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/11/05/390843.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/390843.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/390843.html</trackback:ping><description><![CDATA[<p>package com.abin.lee.servlet.mythread.runnable;</p>
<p>import java.util.concurrent.atomic.AtomicInteger;</p>
<p>public class SumThread implements Runnable{<br />&nbsp;private&nbsp; AtomicInteger num=new AtomicInteger(0);<br />&nbsp;public void run(){<br />&nbsp;&nbsp;while(num.get()&lt;100){<br />&nbsp;&nbsp;&nbsp;try {<br />&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(100);<br />&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;// TODO Auto-generated catch block<br />&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;if(num.get()==40){<br />&nbsp;&nbsp;&nbsp;&nbsp;Thread thread2=new Thread(this,"thread2");<br />&nbsp;&nbsp;&nbsp;&nbsp;thread2.start();<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()+":"+num.getAndIncrement());<br />&nbsp;&nbsp;}<br />&nbsp;}<br />&nbsp;<br />}<br /></p><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<p>package com.abin.lee.servlet.mythread.runnable;</p>
<p>public class SumThreadTest {<br />&nbsp;public static void main(String[] args) {<br />&nbsp;&nbsp;SumThread ru=new SumThread();<br />&nbsp;&nbsp;Thread thread1=new Thread(ru,"thread1");<br />&nbsp;&nbsp;thread1.start();<br />&nbsp;}<br />}<br /></p><img src ="http://www.blogjava.net/stevenjohn/aggbug/390843.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-11-05 22:40 <a href="http://www.blogjava.net/stevenjohn/archive/2012/11/05/390843.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java volatile(一)</title><link>http://www.blogjava.net/stevenjohn/archive/2012/10/18/389795.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 18 Oct 2012 02:38:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/10/18/389795.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/389795.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/10/18/389795.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/389795.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/389795.html</trackback:ping><description><![CDATA[<pre id="best-answer-content" class="reply-text mb10" data-accusearea="aContent">Volatile修饰的成员变量在每次被线程访问时，都强迫从共享内存中重读该成员变量的值。而且，当成员变量发生变化时，强迫线程将变化值回写到共享内存。这样在任何时刻，</pre><pre class="reply-text mb10" data-accusearea="aContent">两个不同的线程总是看到某个成员变量的同一个值。

Java语言规范中指出：为了获得最佳速度，允许线程保存共享成员变量的私有拷贝，而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。

这样当多个线程同时与某个对象交互时，就必须要注意到要让线程及时的得到共享成员变量的变化。

而volatile关键字就是提示VM：对于这个成员变量不能保存它的私有拷贝，而应直接与共享成员变量交互。

使用建议：在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中，或者为常量时，不必使用。

由于使用volatile屏蔽掉了VM中必要的代码优化，所以在效率上比较低，因此一定在必要时才使用此关键字。 


就跟C中的一样 禁止编译器进行优化~~~~</pre>在并发中可保证内存一致性<br />volatile声明的变量只在主存中存储<br />读取的时候，会有读取脏数据的情况发生<br />但是写数据的时候，是能保证数据能正确写入<br /><br />volatile只保证每次都从主存拿数据，其他保证不了什么吧？<br />告诉编译器不要使用缓存<br /><br />非long、double变量不能保证原子性，非volatile变量不能保证内存可见性。<br /><br />volatile 还能防止reorder...<br />就是内存屏蔽，防止指令重拍<br />其实目的就是保证可见性<br />可以操作volatile...变量 但是不代表你的操作指令是原子的<br /><br /><br /><br /><br /><br /><br /><br /><br /><img src ="http://www.blogjava.net/stevenjohn/aggbug/389795.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-10-18 10:38 <a href="http://www.blogjava.net/stevenjohn/archive/2012/10/18/389795.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中volatile关键字的含义</title><link>http://www.blogjava.net/stevenjohn/archive/2012/10/18/389796.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 18 Oct 2012 02:38:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/10/18/389796.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/389796.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/10/18/389796.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/389796.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/389796.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body">
<p>在java线程并发处理中，有一个关键字volatile的使用目前存在很大的混淆，以为使用这个关键字，在进行多线程并发处理的时候就可以万事大吉。</p>
<p>Java语言是支持多线程的，为了解决线程并发的问题，在语言内部引入了 同步块 和 volatile 关键字机制。</p>
<p>&nbsp;</p>
<p><strong>synchronized</strong>&nbsp;</p>
<p>同步块大家都比较熟悉，通过 synchronized 关键字来实现，所有加上synchronized 和 块语句，在多线程访问的时候，同一时刻只能有一个线程能够用</p>
<p>synchronized 修饰的方法 或者 代码块。</p>
<p>&nbsp;</p>
<p><strong>volatile</strong></p>
<p>用volatile修饰的变量，线程在每次使用变量的时候，都会读取变量修改后的最的值。volatile很容易被误用，用来进行原子性操作。</p>
<p>&nbsp;</p>
<p>下面看一个例子，我们实现一个计数器，每次线程启动的时候，会调用计数器inc方法，对计数器进行加一</p>
<p>&nbsp;</p>
<p>执行环境&#8212;&#8212;jdk版本：jdk1.6.0_31 ，内存 ：3G&nbsp;&nbsp; cpu：x86 2.4G</p>
<div>
<div id="highlighter_781773" class="syntaxhighlighter  java ie">
<div class="toolbar"><span><a class="toolbar_item command_help help" href="http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html#">?</a></span></div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
<div class="line number20 index19 alt1">20</div>
<div class="line number21 index20 alt2">21</div>
<div class="line number22 index21 alt1">22</div>
<div class="line number23 index22 alt2">23</div>
<div class="line number24 index23 alt1">24</div>
<div class="line number25 index24 alt2">25</div>
<div class="line number26 index25 alt1">26</div>
<div class="line number27 index26 alt2">27</div>
<div class="line number28 index27 alt1">28</div>
<div class="line number29 index28 alt2">29</div>
<div class="line number30 index29 alt1">30</div>
<div class="line number31 index30 alt2">31</div>
<div class="line number32 index31 alt1">32</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="java keyword">public</code> <code class="java keyword">class</code> <code class="java plain">Counter { </code></div>
<div class="line number2 index1 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number3 index2 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">public</code> <code class="java keyword">static</code> <code class="java keyword">int</code> <code class="java plain">count = </code><code class="java value">0</code><code class="java plain">; </code></div>
<div class="line number4 index3 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number5 index4 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">public</code> <code class="java keyword">static</code> <code class="java keyword">void</code> <code class="java plain">inc() { </code></div>
<div class="line number6 index5 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number7 index6 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java comments">//这里延迟1毫秒，使得结果明显 </code></div>
<div class="line number8 index7 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">try</code> <code class="java plain">{ </code></div>
<div class="line number9 index8 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">Thread.sleep(</code><code class="java value">1</code><code class="java plain">); </code></div>
<div class="line number10 index9 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code><code class="java keyword">catch</code> <code class="java plain">(InterruptedException e) { </code></div>
<div class="line number11 index10 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number12 index11 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number13 index12 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">count++; </code></div>
<div class="line number14 index13 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number15 index14 alt2"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number16 index15 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">public</code> <code class="java keyword">static</code> <code class="java keyword">void</code> <code class="java plain">main(String[] args) { </code></div>
<div class="line number17 index16 alt2"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number18 index17 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java comments">//同时启动1000个线程，去进行i++计算，看看实际结果 </code></div>
<div class="line number19 index18 alt2"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number20 index19 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">for</code> <code class="java plain">(</code><code class="java keyword">int</code> <code class="java plain">i = </code><code class="java value">0</code><code class="java plain">; i &lt; </code><code class="java value">1000</code><code class="java plain">; i++) { </code></div>
<div class="line number21 index20 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">new</code> <code class="java plain">Thread(</code><code class="java keyword">new</code> <code class="java plain">Runnable() { </code></div>
<div class="line number22 index21 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java color1">@Override</code></div>
<div class="line number23 index22 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">public</code> <code class="java keyword">void</code> <code class="java plain">run() { </code></div>
<div class="line number24 index23 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">Counter.inc(); </code></div>
<div class="line number25 index24 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number26 index25 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">}).start(); </code></div>
<div class="line number27 index26 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number28 index27 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number29 index28 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java comments">//这里每次运行的值都有可能不同,可能为1000 </code></div>
<div class="line number30 index29 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">System.out.println(</code><code class="java string">"运行结果:Counter.count="</code> <code class="java plain">+ Counter.count); </code></div>
<div class="line number31 index30 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number32 index31 alt1"><code class="java plain">}</code></div></div></td></tr></tbody></table></div></div>
<div>
<div id="highlighter_207497" class="syntaxhighlighter  java ie">
<div class="toolbar"><span><a class="toolbar_item command_help help" href="http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html#">?</a></span></div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="java spaces">&nbsp;</code>&nbsp;</div></div></td></tr></tbody></table></div></div>
<div>
<div id="highlighter_394959" class="syntaxhighlighter  java ie">
<div class="toolbar"><span><a class="toolbar_item command_help help" href="http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html#">?</a></span></div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="java plain">运行结果:Counter.count=</code><code class="java value">995</code></div></div></td></tr></tbody></table></div></div>
<div>
<div id="highlighter_577791" class="syntaxhighlighter  java ie">
<div class="toolbar"><span><a class="toolbar_item command_help help" href="http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html#">?</a></span></div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="java plain">实际运算结果每次可能都不一样，本机的结果为：运行结果:Counter.count=</code><code class="java value">995</code><code class="java plain">，可以看出，在多线程的环境下，Counter.count并没有期望结果是</code><code class="java value">1000</code></div></div></td></tr></tbody></table></div></div>
<div>
<div id="highlighter_538327" class="syntaxhighlighter  java ie">
<div class="toolbar"><span><a class="toolbar_item command_help help" href="http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html#">?</a></span></div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="java spaces">&nbsp;</code>&nbsp;</div></div></td></tr></tbody></table></div></div>
<div>
<div id="highlighter_563299" class="syntaxhighlighter  java ie">
<div class="toolbar"><span><a class="toolbar_item command_help help" href="http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html#">?</a></span></div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="java plain">很多人以为，这个是多线程并发问题，只需要在变量count之前加上</code><code class="java keyword">volatile</code><code class="java plain">就可以避免这个问题，那我们在修改代码看看，看看结果是不是符合我们的期望</code></div></div></td></tr></tbody></table></div></div>
<div>
<div id="highlighter_48983" class="syntaxhighlighter  java ie">
<div class="toolbar"><span><a class="toolbar_item command_help help" href="http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html#">?</a></span></div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div>
<div class="line number15 index14 alt2">15</div>
<div class="line number16 index15 alt1">16</div>
<div class="line number17 index16 alt2">17</div>
<div class="line number18 index17 alt1">18</div>
<div class="line number19 index18 alt2">19</div>
<div class="line number20 index19 alt1">20</div>
<div class="line number21 index20 alt2">21</div>
<div class="line number22 index21 alt1">22</div>
<div class="line number23 index22 alt2">23</div>
<div class="line number24 index23 alt1">24</div>
<div class="line number25 index24 alt2">25</div>
<div class="line number26 index25 alt1">26</div>
<div class="line number27 index26 alt2">27</div>
<div class="line number28 index27 alt1">28</div>
<div class="line number29 index28 alt2">29</div>
<div class="line number30 index29 alt1">30</div>
<div class="line number31 index30 alt2">31</div>
<div class="line number32 index31 alt1">32</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="java keyword">public</code> <code class="java keyword">class</code> <code class="java plain">Counter { </code></div>
<div class="line number2 index1 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number3 index2 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">public</code> <code class="java keyword">volatile</code> <code class="java keyword">static</code> <code class="java keyword">int</code> <code class="java plain">count = </code><code class="java value">0</code><code class="java plain">; </code></div>
<div class="line number4 index3 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number5 index4 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">public</code> <code class="java keyword">static</code> <code class="java keyword">void</code> <code class="java plain">inc() { </code></div>
<div class="line number6 index5 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number7 index6 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java comments">//这里延迟1毫秒，使得结果明显 </code></div>
<div class="line number8 index7 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">try</code> <code class="java plain">{ </code></div>
<div class="line number9 index8 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">Thread.sleep(</code><code class="java value">1</code><code class="java plain">); </code></div>
<div class="line number10 index9 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code><code class="java keyword">catch</code> <code class="java plain">(InterruptedException e) { </code></div>
<div class="line number11 index10 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number12 index11 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number13 index12 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">count++; </code></div>
<div class="line number14 index13 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number15 index14 alt2"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number16 index15 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">public</code> <code class="java keyword">static</code> <code class="java keyword">void</code> <code class="java plain">main(String[] args) { </code></div>
<div class="line number17 index16 alt2"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number18 index17 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java comments">//同时启动1000个线程，去进行i++计算，看看实际结果 </code></div>
<div class="line number19 index18 alt2"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number20 index19 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">for</code> <code class="java plain">(</code><code class="java keyword">int</code> <code class="java plain">i = </code><code class="java value">0</code><code class="java plain">; i &lt; </code><code class="java value">1000</code><code class="java plain">; i++) { </code></div>
<div class="line number21 index20 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">new</code> <code class="java plain">Thread(</code><code class="java keyword">new</code> <code class="java plain">Runnable() { </code></div>
<div class="line number22 index21 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java color1">@Override</code></div>
<div class="line number23 index22 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java keyword">public</code> <code class="java keyword">void</code> <code class="java plain">run() { </code></div>
<div class="line number24 index23 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">Counter.inc(); </code></div>
<div class="line number25 index24 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number26 index25 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">}).start(); </code></div>
<div class="line number27 index26 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number28 index27 alt1"><code class="java spaces">&nbsp;</code>&nbsp;</div>
<div class="line number29 index28 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java comments">//这里每次运行的值都有可能不同,可能为1000 </code></div>
<div class="line number30 index29 alt1"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">System.out.println(</code><code class="java string">"运行结果:Counter.count="</code> <code class="java plain">+ Counter.count); </code></div>
<div class="line number31 index30 alt2"><code class="java spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="java plain">} </code></div>
<div class="line number32 index31 alt1"><code class="java plain">}</code></div></div></td></tr></tbody></table></div></div>
<p>运行结果:Counter.count=992</p>
<p>运行结果还是没有我们期望的1000，下面我们分析一下原因</p>
<p>&nbsp;</p>
<p>在 java 垃圾回收整理一文中，描述了jvm运行时刻内存的分配。其中有一个内存区域是jvm虚拟机栈，每一个线程运行时都有一个线程栈，</p>
<p>线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候，首先通过对象的引用找到对应在堆内存的变量的值，然后把堆内存</p>
<p>变量的具体值load到线程本地内存中，建立一个变量副本，之后线程就不再和对象在堆内存变量值有任何关系，而是直接修改副本变量的值，</p>
<p>在修改完之后的某一个时刻（线程退出之前），自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。下面一幅图</p>
<p>描述这写交互</p>
<p>&nbsp;</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/aigongsi/201204/201204011757234696.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="java volatile1" border="0" alt="java volatile1" src="http://images.cnblogs.com/cnblogs_com/aigongsi/201204/201204011757235219.jpg" width="579" height="555" data-pinit="registered" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>read and load 从主存复制变量到当前工作内存<br />use and assign&nbsp; 执行代码，改变共享变量值 <br />store and write 用工作内存数据刷新主存相关内容</p>
<p>其中use and assign 可以多次出现</p>
<p>但是这一些操作并不是原子性，也就是 在read load之后，如果主内存count变量发生修改之后，线程工作内存中的值由于已经加载，不会产生对应的变化，所以计算出来的结果会和预期不一样</p>
<p>对于volatile修饰的变量，jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的</p>
<p>例如假如线程1，线程2 在进行read,load 操作中，发现主内存中count的值都是5，那么都会加载这个最新的值</p>
<p>在线程1堆count进行修改之后，会write到主内存中，主内存中的count变量就会变为6</p>
<p>线程2由于已经进行read,load操作，在进行运算之后，也会更新主内存count的变量值为6</p>
<p>导致两个线程及时用volatile关键字修改之后，还是会存在并发的情况。</p></div>
<div id="MySignature">
<p style="border-bottom: rgb(224,224,224) 1px dashed; border-left: rgb(224,224,224) 1px dashed; padding-bottom: 10px; padding-left: 10px; padding-right: 10px;background: rgb(230,230,230); border-top: rgb(224,224,224) 1px dashed; border-right: rgb(224,224,224) 1px dashed; padding-top: 10px"  http: www.cnblogs.com aigongsi ? target="_blank">爱公司的程序员</a> <br />博客园blog地址:<a href="http://www.cnblogs.com/aigongsi/" target="_blank">http://www.cnblogs.com/aigongsi/</a> <br />本人版权归作者和博客园所有，欢迎转载，转载请注明出处。 </p></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/389796.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-10-18 10:38 <a href="http://www.blogjava.net/stevenjohn/archive/2012/10/18/389796.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 三种方式实现多线程</title><link>http://www.blogjava.net/stevenjohn/archive/2012/10/12/389493.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Fri, 12 Oct 2012 15:41:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/10/12/389493.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/389493.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/10/12/389493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/389493.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/389493.html</trackback:ping><description><![CDATA[<span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">第一种：（Thread）</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" />
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">package com.abin.lee.servlet.mythread.thread;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">public class Mythread extends Thread{<br />&nbsp;private String name;<br />&nbsp;public Mythread(String name) {<br />&nbsp;&nbsp;this.name=name;<br />&nbsp;}<br />&nbsp;public void run() {<br />&nbsp;&nbsp;synchronized(this.name){<br />&nbsp;&nbsp;&nbsp;System.out.println("开始时间："+System.currentTimeMillis()+",线程名字："+Thread.currentThread().getName());<br />&nbsp;&nbsp;&nbsp;System.out.println("name="+name);<br />&nbsp;&nbsp;&nbsp;System.out.println("结束时间："+System.currentTimeMillis()+",线程名字："+Thread.currentThread().getName());<br />&nbsp;<br />&nbsp;&nbsp;}<br />&nbsp;}<br />&nbsp;<br />}<br /></p><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">测试代码：</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" />
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">package com.abin.lee.servlet.mythread.thread;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">public class MythreadTest {<br />&nbsp;public static void main(String[] args) {<br />&nbsp;&nbsp;Mythread mythread1=new Mythread("ManyThread");<br />&nbsp;&nbsp;Mythread mythread2=new Mythread("ManyThread");<br />&nbsp;&nbsp;mythread1.start();<br />&nbsp;&nbsp;mythread2.start();<br />&nbsp;}</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">}<br /></p><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">第二种：（Runnable）</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" />
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">package com.abin.lee.servlet.mythread.runnable;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">public class MyRunnable implements Runnable{<br />&nbsp;private String name;<br />&nbsp;public MyRunnable(String name) {<br />&nbsp;&nbsp;this.name=name;<br />&nbsp;}<br />&nbsp;public synchronized void run(){<br />&nbsp;&nbsp;&nbsp;System.out.println("开始时间："+System.currentTimeMillis()+",线程名字："+Thread.currentThread().getName());<br />&nbsp;&nbsp;&nbsp;System.out.println("name="+name);<br />&nbsp;&nbsp;&nbsp;try {<br />&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(3000);<br />&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;System.out.println("结束时间："+System.currentTimeMillis()+",线程名字："+Thread.currentThread().getName());<br />&nbsp;}<br />}<br /></p><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">测试代码：</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" />
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">package com.abin.lee.servlet.mythread.runnable;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">public class MyRunnableTest {<br />&nbsp;public static void main(String[] args) {<br />&nbsp;&nbsp;MyRunnable myRunnable=new MyRunnable("ManyThread");<br />&nbsp;&nbsp;Thread thread1=new Thread(myRunnable);<br />&nbsp;&nbsp;Thread thread2=new Thread(myRunnable);<br />&nbsp;&nbsp;thread1.start();<br />&nbsp;&nbsp;thread2.start();<br />&nbsp;}<br />}<br /></p><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">第三种：（Callable）这种说明一下，这个实现多线程的方式是在JDK1.5引进的，在java.util.concurrent.Callable&nbsp; 这个并发包下面，并且提供同步返回结果的多线程。</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" />
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">package com.abin.lee.servlet.mythread.callable;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">import java.util.concurrent.Callable;<br />import java.util.concurrent.locks.Lock;<br />import java.util.concurrent.locks.ReentrantLock;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">public class MyCallable implements Callable&lt;String&gt;{<br />&nbsp;private String name;<br />&nbsp;public MyCallable(String name) {<br />&nbsp;&nbsp;this.name=name;<br />&nbsp;}<br />&nbsp;public String call() throws Exception {<br />&nbsp;&nbsp;Lock lock=new ReentrantLock();<br />&nbsp;&nbsp;lock.lock();<br />&nbsp;&nbsp;String result="";<br />&nbsp;&nbsp;try {<br />&nbsp;&nbsp;&nbsp;System.out.println("开始时间："+System.currentTimeMillis()+",线程名字："+Thread.currentThread().getName());<br />&nbsp;&nbsp;&nbsp;System.out.println("name="+name);<br />&nbsp;&nbsp;&nbsp;if(name.equals("ManyThread")){<br />&nbsp;&nbsp;&nbsp;&nbsp;result="success";<br />&nbsp;&nbsp;&nbsp;}else{<br />&nbsp;&nbsp;&nbsp;&nbsp;result="failure";<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;try {<br />&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(3000);<br />&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;System.out.println("结束时间："+System.currentTimeMillis()+",线程名字："+Thread.currentThread().getName());<br />&nbsp;<br />&nbsp;&nbsp;} catch (Exception e) {<br />&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;}finally{<br />&nbsp;&nbsp;&nbsp;lock.unlock();<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return result;&nbsp;&nbsp;<br />&nbsp;}<br />&nbsp;<br />}<br /></p><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">测试代码：</span><br style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" />
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">package com.abin.lee.servlet.mythread.callable;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">import java.util.concurrent.ExecutionException;<br />import java.util.concurrent.ExecutorService;<br />import java.util.concurrent.Executors;<br />import java.util.concurrent.Future;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">import org.junit.Test;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">public class MyCallableTest {<br />&nbsp;@Test<br />&nbsp;public void testMyCallable() throws InterruptedException, ExecutionException{<br />&nbsp;&nbsp;ExecutorService executor=Executors.newFixedThreadPool(3);<br />&nbsp;&nbsp;MyCallable myCallable=new MyCallable("ManyThread");<br />&nbsp;&nbsp;Future future1=executor.submit(myCallable);<br />&nbsp;&nbsp;System.out.println("future1="+future1.get());<br />&nbsp;&nbsp;Future future2=executor.submit(myCallable);<br />&nbsp;&nbsp;System.out.println("future2="+future2.get());<br />&nbsp;&nbsp;Future future3=executor.submit(myCallable);<br />&nbsp;&nbsp;System.out.println("future3="+future3.get());<br />&nbsp;&nbsp;<br />&nbsp;}</p>
<p style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">}<br /><br />测试结果：<br /></p>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">开始时间：1350056647659,线程名字：pool-1-thread-1</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">name=ManyThread</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">结束时间：1350056650661,线程名字：pool-1-thread-1</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">future1=success</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">开始时间：1350056650661,线程名字：pool-1-thread-2</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">name=ManyThread</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">结束时间：1350056653661,线程名字：pool-1-thread-2</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">future2=success</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">开始时间：1350056653662,线程名字：pool-1-thread-3</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">name=ManyThread</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">结束时间：1350056656663,线程名字：pool-1-thread-3</div>
<div style="widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 13px/17px verdana, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">future3=success</div><img src ="http://www.blogjava.net/stevenjohn/aggbug/389493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-10-12 23:41 <a href="http://www.blogjava.net/stevenjohn/archive/2012/10/12/389493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java ThreadLocal&lt;Connection&gt;</title><link>http://www.blogjava.net/stevenjohn/archive/2012/09/01/386757.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sat, 01 Sep 2012 09:03:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/09/01/386757.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/386757.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/09/01/386757.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/386757.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/386757.html</trackback:ping><description><![CDATA[<div>//ThreadLocal第一种用法：<br /><br />//建表：<br /><div>-- Create table</div><div>create table USERBEAN</div><div>(</div><div>&nbsp; ID &nbsp; &nbsp; &nbsp; NVARCHAR2(40) not null,</div><div>&nbsp; USERNAME NVARCHAR2(40),</div><div>&nbsp; PASSWORD NVARCHAR2(40)</div><div>)</div><div>tablespace USERS</div><div>&nbsp; pctfree 10</div><div>&nbsp; initrans 1</div><div>&nbsp; maxtrans 255</div><div>&nbsp; storage</div><div>&nbsp; (</div><div>&nbsp; &nbsp; initial 64K</div><div>&nbsp; &nbsp; minextents 1</div><div>&nbsp; &nbsp; maxextents unlimited</div><div>&nbsp; );</div><div>-- Create/Recreate primary, unique and foreign key constraints&nbsp;</div><div>alter table USERBEAN</div><div>&nbsp; add constraint SSSID primary key (ID)</div><div>&nbsp; using index&nbsp;</div><div>&nbsp; tablespace USERS</div><div>&nbsp; pctfree 10</div><div>&nbsp; initrans 2</div><div>&nbsp; maxtrans 255</div><div>&nbsp; storage</div><div>&nbsp; (</div><div>&nbsp; &nbsp; initial 64K</div><div>&nbsp; &nbsp; minextents 1</div><div>&nbsp; &nbsp; maxextents unlimited</div><div>&nbsp; );</div><div><br /><br /><br /><br /><br /></div>package com.abin.lee.collection.threadlocal;</div><div></div><div>import java.sql.Connection;</div><div>import java.sql.DriverManager;</div><div>import java.sql.SQLException;</div><div></div><div>public class MyThreadLocal {</div><div><span style="white-space:pre">	</span>//使用ThreadLocal保存Connection变量</div><div><span style="white-space:pre">	</span>public static ThreadLocal&lt;Connection&gt; threadLocal = new ThreadLocal&lt;Connection&gt;();</div><div><span style="white-space:pre">	</span>private static final String URL = "jdbc:oracle:thin:@localhost:1521:XE";</div><div><span style="white-space:pre">	</span>private static final String USERNAME = "abing";</div><div><span style="white-space:pre">	</span>private static final String PWD = "abing";</div><div></div><div><span style="white-space:pre">	</span>public static Connection getConnection() {</div><div><span style="white-space:pre">		</span>Connection connection = null;</div><div><span style="white-space:pre">		</span>String url = "";</div><div><span style="white-space:pre">		</span>//如果connThreadLocal没有本线程对应的Connection创建一个新的Connection，并将其保存到线程本地变量中。</div><div><span style="white-space:pre">		</span>if (threadLocal.get() == null) {</div><div><span style="white-space:pre">			</span>try {</div><div><span style="white-space:pre">				</span>Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();</div><div><span style="white-space:pre">				</span>connection = DriverManager.getConnection(URL, USERNAME, PWD);</div><div><span style="white-space:pre">				</span>threadLocal.set(connection);</div><div><span style="white-space:pre">			</span>} catch (Exception e) {</div><div><span style="white-space:pre">				</span>e.printStackTrace();</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">		</span>}else {</div><div><span style="white-space:pre">			</span>return threadLocal.get();//直接返回线程本地变量</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">		</span>return connection;</div><div><span style="white-space:pre">	</span>}</div><div></div><div><span style="white-space:pre">	</span></div><div></div><div><span style="white-space:pre">	</span>public static void remove() {</div><div><span style="white-space:pre">		</span>threadLocal.remove();</div><div><span style="white-space:pre">	</span>}</div><div>}</div><div><br /><br /><br /><br /><div>package com.abin.lee.collection.threadlocal;</div><div></div><div>import java.io.Serializable;</div><div></div><div>public class UserBean implements Serializable{</div><div><span style="white-space:pre">	</span>private String id;</div><div><span style="white-space:pre">	</span>private String username;</div><div><span style="white-space:pre">	</span>private String password;</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span>public String getId() {</div><div><span style="white-space:pre">		</span>return id;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public void setId(String id) {</div><div><span style="white-space:pre">		</span>this.id = id;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public String getUsername() {</div><div><span style="white-space:pre">		</span>return username;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public void setUsername(String username) {</div><div><span style="white-space:pre">		</span>this.username = username;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public String getPassword() {</div><div><span style="white-space:pre">		</span>return password;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public void setPassword(String password) {</div><div><span style="white-space:pre">		</span>this.password = password;</div><div><span style="white-space:pre">	</span>}</div><div>}</div><div></div><br /><br /><br /><br /><br />//测试代码<br /><div>package com.abin.lee.collection.threadlocal;</div><div></div><div>import java.sql.Connection;</div><div>import java.sql.PreparedStatement;</div><div>import java.sql.ResultSet;</div><div>import java.util.ArrayList;</div><div>import java.util.List;</div><div></div><div>public class OracleOperate {</div><div><span style="white-space:pre">	</span>public static List&lt;UserBean&gt; findAll(){</div><div><span style="white-space:pre">		</span>Connection conn=null;</div><div><span style="white-space:pre">		</span>PreparedStatement ps=null;</div><div><span style="white-space:pre">		</span>ResultSet rs=null;</div><div><span style="white-space:pre">		</span>String sql="select * from userbean order by id desc";</div><div><span style="white-space:pre">		</span>List&lt;UserBean&gt; list=new ArrayList&lt;UserBean&gt;();</div><div><span style="white-space:pre">		</span>UserBean user=null;</div><div><span style="white-space:pre">		</span>try {</div><div><span style="white-space:pre">			</span>conn=MyThreadLocal.getConnection();</div><div><span style="white-space:pre">			</span>ps=conn.prepareStatement(sql);</div><div><span style="white-space:pre">			</span>rs=ps.executeQuery();</div><div><span style="white-space:pre">			</span>while (rs.next()&amp;&amp;rs!=null) {</div><div><span style="white-space:pre">				</span>user=new UserBean();</div><div><span style="white-space:pre">				</span>user.setId(rs.getString("id"));</div><div><span style="white-space:pre">				</span>user.setUsername(rs.getString("username"));</div><div><span style="white-space:pre">				</span>user.setPassword(rs.getString("password"));</div><div><span style="white-space:pre">				</span>list.add(user);</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">		</span>} catch (Exception e) {</div><div><span style="white-space:pre">			</span>e.printStackTrace();</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">		</span>return list;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public static void main(String[] args) {</div><div><span style="white-space:pre">		</span>List&lt;UserBean&gt; list=findAll();</div><div><span style="white-space:pre">		</span>for(UserBean lst:list){</div><div><span style="white-space:pre">			</span>System.out.println("id="+lst.getId());</div><div><span style="white-space:pre">			</span>System.out.println("username="+lst.getUsername());</div><div><span style="white-space:pre">			</span>System.out.println("id="+lst.getPassword());</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">	</span>}</div><div></div><div>}<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />//ThreadLocal第二种用法：&nbsp;<br /><div>package com.abin.lee.collection.threadlocal;</div><div></div><div>import java.sql.Connection;</div><div>import java.sql.DriverManager;</div><div>import java.sql.SQLException;</div><div></div><div>public class MyThreadLocal {</div><div><span style="white-space:pre">	</span>private static final String URL = "jdbc:oracle:thin:@localhost:1521:XE";</div><div><span style="white-space:pre">	</span>private static final String USERNAME = "abing";</div><div><span style="white-space:pre">	</span>private static final String PWD = "abing";</div><div></div><div><span style="white-space:pre">	</span>//使用ThreadLocal保存Connection变量</div><div><span style="white-space:pre">	</span>public static ThreadLocal&lt;Connection&gt; threadLocal = new ThreadLocal&lt;Connection&gt;(){</div><div><span style="white-space:pre">		</span>protected Connection initialValue() {</div><div><span style="white-space:pre">			</span>Connection connection = null;</div><div><span style="white-space:pre">			</span>//如果connThreadLocal没有本线程对应的Connection创建一个新的Connection，并将其保存到线程本地变量中。</div><div><span style="white-space:pre">			</span>if (connection == null) {</div><div><span style="white-space:pre">				</span>try {</div><div><span style="white-space:pre">					</span>Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();</div><div><span style="white-space:pre">					</span>connection = DriverManager.getConnection(URL, USERNAME, PWD);</div><div><span style="white-space:pre">				</span>} catch (Exception e) {</div><div><span style="white-space:pre">					</span>e.printStackTrace();</div><div><span style="white-space:pre">				</span>}</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">			</span>return connection;</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">		</span></div><div><span style="white-space:pre">	</span>};</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span>public static Connection getConnection() {</div><div><span style="white-space:pre">		</span>return threadLocal.get();</div><div><span style="white-space:pre">	</span>}</div><div></div><div></div><div><span style="white-space:pre">	</span>public static void remove() {</div><div><span style="white-space:pre">		</span>threadLocal.remove();</div><div><span style="white-space:pre">	</span>}</div><div>}</div><div><br /><br /><br /><br /><div>package com.abin.lee.collection.threadlocal;</div><div></div><div>import java.io.Serializable;</div><div></div><div>public class UserBean implements Serializable{</div><div><span style="white-space:pre">	</span>private String id;</div><div><span style="white-space:pre">	</span>private String username;</div><div><span style="white-space:pre">	</span>private String password;</div><div><span style="white-space:pre">	</span></div><div><span style="white-space:pre">	</span>public String getId() {</div><div><span style="white-space:pre">		</span>return id;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public void setId(String id) {</div><div><span style="white-space:pre">		</span>this.id = id;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public String getUsername() {</div><div><span style="white-space:pre">		</span>return username;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public void setUsername(String username) {</div><div><span style="white-space:pre">		</span>this.username = username;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public String getPassword() {</div><div><span style="white-space:pre">		</span>return password;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public void setPassword(String password) {</div><div><span style="white-space:pre">		</span>this.password = password;</div><div><span style="white-space:pre">	</span>}</div><div>}</div><div></div><br /><br /><br /><br /><br /><br /><div>package com.abin.lee.collection.threadlocal;</div><div></div><div>import java.sql.Connection;</div><div>import java.sql.PreparedStatement;</div><div>import java.sql.ResultSet;</div><div>import java.util.ArrayList;</div><div>import java.util.List;</div><div></div><div>public class OracleOperate {</div><div><span style="white-space:pre">	</span>public static List&lt;UserBean&gt; findAll(){</div><div><span style="white-space:pre">		</span>Connection conn=null;</div><div><span style="white-space:pre">		</span>PreparedStatement ps=null;</div><div><span style="white-space:pre">		</span>ResultSet rs=null;</div><div><span style="white-space:pre">		</span>String sql="select * from userbean order by id desc";</div><div><span style="white-space:pre">		</span>List&lt;UserBean&gt; list=new ArrayList&lt;UserBean&gt;();</div><div><span style="white-space:pre">		</span>UserBean user=null;</div><div><span style="white-space:pre">		</span>try {</div><div><span style="white-space:pre">			</span>conn=MyThreadLocal.getConnection();</div><div><span style="white-space:pre">			</span>ps=conn.prepareStatement(sql);</div><div><span style="white-space:pre">			</span>rs=ps.executeQuery();</div><div><span style="white-space:pre">			</span>while (rs.next()&amp;&amp;rs!=null) {</div><div><span style="white-space:pre">				</span>user=new UserBean();</div><div><span style="white-space:pre">				</span>user.setId(rs.getString("id"));</div><div><span style="white-space:pre">				</span>user.setUsername(rs.getString("username"));</div><div><span style="white-space:pre">				</span>user.setPassword(rs.getString("password"));</div><div><span style="white-space:pre">				</span>list.add(user);</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">		</span>} catch (Exception e) {</div><div><span style="white-space:pre">			</span>e.printStackTrace();</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">		</span>return list;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public static void main(String[] args) {</div><div><span style="white-space:pre">		</span>List&lt;UserBean&gt; list=findAll();</div><div><span style="white-space:pre">		</span>for(UserBean lst:list){</div><div><span style="white-space:pre">			</span>System.out.println("id="+lst.getId());</div><div><span style="white-space:pre">			</span>System.out.println("username="+lst.getUsername());</div><div><span style="white-space:pre">			</span>System.out.println("id="+lst.getPassword());</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">	</span>}</div><div></div><div>}</div><div></div></div></div><div></div></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/386757.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-09-01 17:03 <a href="http://www.blogjava.net/stevenjohn/archive/2012/09/01/386757.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Volatile操作多线程</title><link>http://www.blogjava.net/stevenjohn/archive/2012/09/01/386753.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sat, 01 Sep 2012 07:56:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/09/01/386753.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/386753.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/09/01/386753.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/386753.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/386753.html</trackback:ping><description><![CDATA[<div>package com.abin.lee.collection.volatiler;</div><div></div><div>public class MyThread implements Runnable{</div><div><span style="white-space:pre">	</span>private volatile boolean flag=false;</div><div><span style="white-space:pre">	</span>public void run() {</div><div><span style="white-space:pre">		</span>while(!flag){</div><div><span style="white-space:pre">			</span>try {</div><div><span style="white-space:pre">				</span>System.out.println("before");</div><div><span style="white-space:pre">				</span>Thread.sleep(3000);</div><div><span style="white-space:pre">				</span>System.out.println("after");</div><div><span style="white-space:pre">			</span>} catch (Exception e) {</div><div><span style="white-space:pre">				</span>e.printStackTrace();</div><div><span style="white-space:pre">			</span>}</div><div><span style="white-space:pre">			</span>flag=true;</div><div><span style="white-space:pre">		</span>}</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span>public void setDone(boolean flag){</div><div><span style="white-space:pre">		</span>this.flag=flag;</div><div><span style="white-space:pre">	</span>}</div><div><span style="white-space:pre">	</span></div><div>}</div><div><br /><br /><br /><br /><br /><br />测试代码：<br /><div>package com.abin.lee.collection.volatiler;</div><div></div><div>public class MyVolatileOne {</div><div><span style="white-space:pre">	</span>public static void main(String[] args) {</div><div><span style="white-space:pre">		</span>MyThread myThread=new MyThread();</div><div><span style="white-space:pre">		</span>Thread thread=new Thread(myThread);</div><div><span style="white-space:pre">		</span>thread.start();</div><div><span style="white-space:pre">	</span>}</div><div>}</div><div></div></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/386753.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-09-01 15:56 <a href="http://www.blogjava.net/stevenjohn/archive/2012/09/01/386753.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 多线程</title><link>http://www.blogjava.net/stevenjohn/archive/2012/08/02/384611.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 02 Aug 2012 07:30:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/08/02/384611.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/384611.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/08/02/384611.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/384611.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/384611.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p><strong>问题解决2&#8212;&#8212;加入等待与唤醒</strong></p>
<p><br />package edu.sjtu.erplab.thread;</p>
<p>class Info{<br />&nbsp;&nbsp;&nbsp; private String name="name";<br />&nbsp;&nbsp;&nbsp; private String content="content";<br />&nbsp;&nbsp;&nbsp; private boolean flag=true;<br />&nbsp;&nbsp;&nbsp; public&nbsp; synchronized void set(String name,String content)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!flag)//标志位为false，不可以生产<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.wait();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO Auto-generated catch block<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.setName(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(30);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO Auto-generated catch block<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.setContent(content);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag=false;//修改标志位为false，表示生产者已经完成资源，消费者可以消费。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.notify();//唤醒消费者进程<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public synchronized void get()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(flag)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.wait();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO Auto-generated catch block<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(30);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO Auto-generated catch block<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(this.getName()+":--&gt;"+this.getContent());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag=true;//修改标志位为true，表示消费者拿走资源，生产者可以生产。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.notify();//唤醒生产者进程。<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public String getName() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return name;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public void setName(String name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.name = name;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public String getContent() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return content;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public void setContent(String content) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.content = content;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />}</p>
<p>class Producer implements Runnable{<br />&nbsp;&nbsp;&nbsp; private Info info=null;<br />&nbsp;&nbsp;&nbsp; public Producer(Info info)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.info=info;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; @Override<br />&nbsp;&nbsp;&nbsp; public void run() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean flag=false;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;10;i++)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(flag)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.info.set("name+"+i, "content+"+i);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag=false;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.info.set("name-"+i, "content-"+i);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag=true;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />}</p>
<p>class Consumer implements Runnable{<br />&nbsp;&nbsp;&nbsp; private Info info=null;<br />&nbsp;&nbsp;&nbsp; public Consumer(Info info)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.info=info;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; @Override<br />&nbsp;&nbsp;&nbsp; public void run() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;10;i++)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(10);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO Auto-generated catch block<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.info.get();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }<br />}</p>
<p>public class ThreadDeadLock {<br />&nbsp;&nbsp;&nbsp; public static void main(String args[])<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Info info=new Info();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Producer pro=new Producer(info);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Consumer con=new Consumer(info);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Thread(pro).start();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Thread(con).start();<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />}<br /><br /><br /><br /><br /><a href="http://www.cnblogs.com/xwdreamer/archive/2011/11/20/2296931.html#2397397">http://www.cnblogs.com/xwdreamer/archive/2011/11/20/2296931.html#2397397</a></p><img src ="http://www.blogjava.net/stevenjohn/aggbug/384611.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-08-02 15:30 <a href="http://www.blogjava.net/stevenjohn/archive/2012/08/02/384611.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>精炼的Java线程Sleep,yield,wait,notify,Synchronized</title><link>http://www.blogjava.net/stevenjohn/archive/2012/06/17/380945.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sat, 16 Jun 2012 17:42:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/06/17/380945.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/380945.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/06/17/380945.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/380945.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/380945.html</trackback:ping><description><![CDATA[多线程 <br />线程：是指进程中的一个执行流程。 <br />线程与进程的区别：每个进程都需要操作系统为其分配独立的内存地址空间，而同一进程中的所有线程在同一块地址空间中工作，这些线程可以共享同一块内存和系统资源。 <br /><br /><br />如何创建一个线程？ <br /><br />创建线程有两种方式，如下： <br />1、 扩展java.lang.Thread类 <br />2、 实现Runnable接口 <br />Thread类代表线程类，它的两个最主要的方法是： <br />run()&#8212;&#8212;包含线程运行时所执行的代码 <br />Start()&#8212;&#8212;用于启动线程 <br /><br />一个线程只能被启动一次。第二次启动时将会抛出java.lang.IllegalThreadExcetpion异常 <br /><br />线程间状态的转换（如图示） <br /><br />新建状态：用new语句创建的线程对象处于新建状态，此时它和其它的java对象一样，仅仅在堆中被分配了内存 <br />就绪状态：当一个线程创建了以后，其他的线程调用了它的start()方法，该线程就进入了就绪状态。处于这个状态的线程位于可运行池中，等待获得CPU的使用权 <br />运行状态：处于这个状态的线程占用CPU,执行程序的代码 <br />阻塞状态：当线程处于阻塞状态时，java虚拟机不会给线程分配CPU，直到线程重新进入就绪状态，它才有机会转到运行状态。 <br />阻塞状态分为三种情况： <br />1、 位于对象等待池中的阻塞状态：当线程运行时，如果执行了某个对象的wait()方法，java虚拟机就回把线程放到这个对象的等待池中 <br />2、 位于对象锁中的阻塞状态，当线程处于运行状态时，试图获得某个对象的同步锁时，如果该对象的同步锁已经被其他的线程占用，JVM就会把这个线程放到这个对象的琐池中。 <br />3、 其它的阻塞状态：当前线程执行了sleep()方法，或者调用了其它线程的join()方法，或者发出了I/O请求时，就会进入这个状态中。 <br /><br />死亡状态：当线程退出了run()方法，就进入了死亡状态，该线程结束了生命周期。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 或者正常退出 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 或者遇到异常退出 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread类的isAlive()方法判断一个线程是否活着，当线程处于死亡状态或者新建状态时，该方法返回false,在其余的状态下，该方法返回true. <br /><br />线程调度 <br />线程调度模型：分时调度模型和抢占式调度模型 <br />JVM采用抢占式调度模型。 <br />所谓的多线程的并发运行，其实是指宏观上看，各个线程轮流获得CPU的使用权，分别执行各自的任务。 <br />（线程的调度不是跨平台，它不仅取决于java虚拟机，它还依赖于操作系统） <br /><br />如果希望明确地让一个线程给另外一个线程运行的机会，可以采取以下的办法之一 <br />1、 调整各个线程的优先级 <br />2、 让处于运行状态的线程调用Thread.sleep()方法 <br />3、 让处于运行状态的线程调用Thread.yield()方法 <br />4、 让处于运行状态的线程调用另一个线程的join()方法 <br /><br />调整各个线程的优先级 <br />Thread类的setPriority(int)和getPriority()方法分别用来设置优先级和读取优先级。 <br />如果希望程序能够移值到各个操作系统中，应该确保在设置线程的优先级时，只使用MAX_PRIORITY、NORM_PRIORITY、MIN_PRIORITY这3个优先级。 <br /><br />线程睡眠：当线程在运行中执行了sleep()方法时，它就会放弃CPU，转到阻塞状态。 <br />线程让步：当线程在运行中执行了Thread类的yield()静态方法时，如果此时具有相同优先级的其它线程处于就绪状态，那么yield()方法将把当前运行的线程放到运行池中并使另一个线程运行。如果没有相同优先级的可运行线程，则yield()方法什么也不做。 <br />Sleep()方法和yield()方法都是Thread类的静态方法，都会使当前处于运行状态的线程放弃CPU，把运行机会让给别的线程，两者的区别在于： <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、sleep()方法会给其他线程运行的机会，而不考虑其他线程的优先级，因此会给较低线程一个运行的机会；yield()方法只会给相同优先级或者更高优先级的线程一个运行的机会。 <br />2、当线程执行了sleep(long millis)方法后，将转到阻塞状态，参数millis指定睡眠时间；当线程执行了yield()方法后，将转到就绪状态。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、sleep()方法声明抛出InterruptedException异常，而yield()方法没有声明抛出任何异常 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、sleep()方法比yield()方法具有更好的移植性 <br /><br />等待其它线程的结束：join() <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当前运行的线程可以调用另一个线程的 join()方法，当前运行的线程将转到阻塞状态，直到另一个线程运行结束，它才恢复运行。 <br /><br />定时器Timer:在JDK的java.util包中提供了一个实用类Timer, 它能够定时执行特定的任务。 <br /><br />线程的同步 <br />原子操作：根据Java规范，对于基本类型的赋值或者返回值操作，是原子操作。但这里的基本数据类型不包括long和double, 因为JVM看到的基本存储单位是32位，而long 和double都要用64位来表示。所以无法在一个时钟周期内完成。 <br /><br />自增操作（++）不是原子操作，因为它涉及到一次读和一次写。 <br /><br />原子操作：由一组相关的操作完成，这些操作可能会操纵与其它的线程共享的资源，为了保证得到正确的运算结果，一个线程在执行原子操作其间，应该采取其他的措施使得其他的线程不能操纵共享资源。 <br /><br />同步代码块：为了保证每个线程能够正常执行原子操作，Java引入了同步机制，具体的做法是在代表原子操作的程序代码前加上synchronized标记，这样的代码被称为同步代码块。 <br /><br />同步锁：每个JAVA对象都有且只有一个同步锁，在任何时刻，最多只允许一个线程拥有这把锁。 <br /><br />当一个线程试图访问带有synchronized(this)标记的代码块时，必须获得 this关键字引用的对象的锁，在以下的两种情况下，本线程有着不同的命运。 <br />1、 假如这个锁已经被其它的线程占用，JVM就会把这个线程放到本对象的锁池中。本线程进入阻塞状态。锁池中可能有很多的线程，等到其他的线程释放了锁，JVM就会从锁池中随机取出一个线程，使这个线程拥有锁，并且转到就绪状态。 <br />2、 假如这个锁没有被其他线程占用，本线程会获得这把锁，开始执行同步代码块。 <br />（一般情况下在执行同步代码块时不会释放同步锁，但也有特殊情况会释放对象锁 <br />如在执行同步代码块时，遇到异常而导致线程终止，锁会被释放；在执行代码块时，执行了锁所属对象的wait()方法，这个线程会释放对象锁，进入对象的等待池中） <br /><br />线程同步的特征： <br />1、 如果一个同步代码块和非同步代码块同时操作共享资源，仍然会造成对共享资源的竞争。因为当一个线程执行一个对象的同步代码块时，其他的线程仍然可以执行对象的非同步代码块。（所谓的线程之间保持同步，是指不同的线程在执行同一个对象的同步代码块时，因为要获得对象的同步锁而互相牵制） <br />2、 每个对象都有唯一的同步锁 <br />3、 在静态方法前面可以使用synchronized修饰符。 <br />4、 当一个线程开始执行同步代码块时，并不意味着必须以不间断的方式运行，进入同步代码块的线程可以执行Thread.sleep()或者执行Thread.yield()方法，此时它并不释放对象锁，只是把运行的机会让给其他的线程。 <br />5、 Synchronized声明不会被继承，如果一个用synchronized修饰的方法被子类覆盖，那么子类中这个方法不在保持同步，除非用synchronized修饰。 <br /><br />线程安全的类： <br />1、 这个类的对象可以同时被多个线程安全的访问。 <br />2、 每个线程都能正常的执行原子操作，得到正确的结果。 <br />3、 在每个线程的原子操作都完成后，对象处于逻辑上合理的状态。 <br /><br />释放对象的锁： <br />1、 执行完同步代码块就会释放对象的锁 <br />2、 在执行同步代码块的过程中，遇到异常而导致线程终止，锁也会被释放 <br />3、 在执行同步代码块的过程中，执行了锁所属对象的wait()方法，这个线程会释放对象锁，进入对象的等待池。 <br /><br />死锁 <br />当一个线程等待由另一个线程持有的锁，而后者正在等待已被第一个线程持有的锁时，就会发生死锁。JVM不监测也不试图避免这种情况，因此保证不发生死锁就成了程序员的责任。 <br /><br />如何避免死锁 <br />一个通用的经验法则是：当几个线程都要访问共享资源A、B、C 时，保证每个线程都按照同样的顺序去访问他们。 <br /><br />线程通信 <br />Java.lang.Object类中提供了两个用于线程通信的方法 <br />1、 wait():执行了该方法的线程释放对象的锁，JVM会把该线程放到对象的等待池中。该线程等待其它线程唤醒 <br />2、 notify():执行该方法的线程唤醒在对象的等待池中等待的一个线程，JVM从对象的等待池中随机选择一个线程，把它转到对象的锁池中。<img src ="http://www.blogjava.net/stevenjohn/aggbug/380945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-06-17 01:42 <a href="http://www.blogjava.net/stevenjohn/archive/2012/06/17/380945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 线程的四种状态</title><link>http://www.blogjava.net/stevenjohn/archive/2012/06/17/380944.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sat, 16 Jun 2012 17:41:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/06/17/380944.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/380944.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/06/17/380944.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/380944.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/380944.html</trackback:ping><description><![CDATA[<div class="body" sizset="2" sizcache="17">
<div class="content" sizset="2" sizcache="17"><pre id="best-answer-content" class="reply-text mb10">来自：开发者在线 
Java多线程程序设计详细解析  
 
一、理解多线程

多线程是这样一种机制，它允许在程序中并发执行多个指令流，每个指令流都称为一个线程，彼此间互相独立。

线程又称为轻量级进程，它和进程一样拥有独立的执行控制，由操作系统负责调度，区别在于线程没有独立的存储空间，而是和所属进程中的其它线程共享一个存储空间，这使得线程间的通信远较进程简单。

多个线程的执行是并发的，也就是在逻辑上&#8220;同时&#8221;，而不管是否是物理上的&#8220;同时&#8221;。如果系统只有一个CPU，那么真正的&#8220;同时&#8221;是不可能的，但是由于CPU的速度非常快，用户感觉不到其中的区别，因此我们也不用关心它，只需要设想各个线程是同时执行即可。

多线程和传统的单线程在程序设计上最大的区别在于，由于各个线程的控制流彼此独立，使得各个线程之间的代码是乱序执行的，由此带来的线程调度，同步等问题，将在以后探讨。

二：在Java中实现多线程

我们不妨设想，为了创建一个新的线程，我们需要做些什么？很显然，我们必须指明这个线程所要执行的代码，而这就是在Java中实现多线程我们所需要做的一切！

真是神奇！Java是如何做到这一点的？通过类！作为一个完全面向对象的语言，Java提供了类java.lang.Thread来方便多线程编程，这个类提供了大量的方法来方便我们控制自己的各个线程，我们以后的讨论都将围绕这个类进行。

那么如何提供给 Java 我们要线程执行的代码呢？让我们来看一看 Thread 类。Thread 类最重要的方法是run()，它为Thread类的方法start()所调用，提供我们的线程所要执行的代码。为了指定我们自己的代码，只需要覆盖它！

方法一：继承 Thread 类，覆盖方法 run()，我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可。下面是一个例子：



public class MyThread extends Thread 
{ 
 int count= 1, number; 
 public MyThread(int num)
{ 
  number = num; 
  System.out.println
("创建线程 " + number); 
 } 
 public void run() { 
  while(true) { 
   System.out.println
("线程 " + number + ":计数 " + count); 
   if(++count== 6) return; 
  } 
 } 
 public static void main(String args[])
{ 
  for(int i = 0; 
i 〈 5; i++) new MyThread(i+1).start(); 
 } 
}
 

这种方法简单明了，符合大家的习惯，但是，它也有一个很大的缺点，那就是如果我们的类已经从一个类继承（如小程序必须继承自 Applet 类），则无法再继承 Thread 类，这时如果我们又不想建立一个新的类，应该怎么办呢？ 

我们不妨来探索一种新的方法：我们不创建Thread类的子类，而是直接使用它，那么我们只能将我们的方法作为参数传递给 Thread 类的实例，有点类似回调函数。但是 Java 没有指针，我们只能传递一个包含这个方法的类的实例。 

那么如何限制这个类必须包含这一方法呢？当然是使用接口！（虽然抽象类也可满足，但是需要继承，而我们之所以要采用这种新方法，不就是为了避免继承带来的限制吗？） 

Java 提供了接口 java.lang.Runnable 来支持这种方法。 

方法二：实现 Runnable 接口 

Runnable接口只有一个方法run()，我们声明自己的类实现Runnable接口并提供这一方法，将我们的线程代码写入其中，就完成了这一部分的任务。但是Runnable接口并没有任何对线程的支持，我们还必须创建Thread类的实例，这一点通过Thread类的构造函数public Thread(Runnable target);来实现。下面是一个例子： 


public class MyThread implements Runnable
{ 
 int count= 1, number; 
 public MyThread(int num)
{ 
  number = num; 
  System.out.println("创建线程 " + number); 
 } 
 public void run()
{ 
  while(true)
{ 
   System.out.println
("线程 " + number + ":计数 " + count); 
   if(++count== 6) return; 
  } 
 } 
 public static void main(String args[])
{ 
  for(int i = 0; i 〈 5;
i++) new Thread(new MyThread(i+1)).start(); 
 } 
}
 

严格地说，创建Thread子类的实例也是可行的，但是必须注意的是，该子类必须没有覆盖 Thread 类的 run 方法，否则该线程执行的将是子类的 run 方法，而不是我们用以实现Runnable 接口的类的 run 方法，对此大家不妨试验一下。 

使用 Runnable 接口来实现多线程使得我们能够在一个类中包容所有的代码，有利于封装，它的缺点在于，我们只能使用一套代码，若想创建多个线程并使各个线程执行不同的代码，则仍必须额外创建类，如果这样的话，在大多数情况下也许还不如直接用多个类分别继承 Thread 来得紧凑。 

综上所述，两种方法各有千秋，大家可以灵活运用。 

下面让我们一起来研究一下多线程使用中的一些问题。 

三、线程的四种状态 

1. 新状态：线程已被创建但尚未执行（start() 尚未被调用）。 

2. 可执行状态：线程可以执行，虽然不一定正在执行。CPU 时间随时可能被分配给该线程，从而使得它执行。 

3. 死亡状态：正常情况下 run() 返回使得线程死亡。调用 stop()或 destroy() 亦有同样效果，但是不被推荐，前者会产生异常，后者是强制终止，不会释放锁。 

4. 阻塞状态：线程不会被分配 CPU 时间，无法执行。 

四、线程的优先级 

线程的优先级代表该线程的重要程度，当有多个线程同时处于可执行状态并等待获得 CPU 时间时，线程调度系统根据各个线程的优先级来决定给谁分配 CPU 时间，优先级高的线程有更大的机会获得 CPU 时间，优先级低的线程也不是没有机会，只是机会要小一些罢了。 

你可以调用 Thread 类的方法 getPriority() 和 setPriority()来存取线程的优先级，线程的优先级界于1(MIN_PRIORITY)和10(MAX_PRIORITY)之间，缺省是5(NORM_PRIORITY)。 

五、线程的同步 

由于同一进程的多个线程共享同一片存储空间，在带来方便的同时，也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突，有效避免了同一个数据对象被多个线程同时访问。 

由于我们可以通过 private 关键字来保证数据对象只能被方法访问，所以我们只需针对方法提出一套机制，这套机制就是 synchronized 关键字，它包括两种用法：synchronized 方法和 synchronized 块。 

1. synchronized 方法：通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如： 


public synchronized void accessVal(int newVal);
 

synchronized 方法控制对类成员变量的访问：每个类实例对应一把锁，每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行，否则所属线程阻塞，方法一旦执行，就独占该锁，直到从该方法返回时才将锁释放，此后被阻塞的线程方能获得该锁，重新进入可执行状态。 

这种机制确保了同一时刻对于每一个类实例，其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态（因为至多只有一个能够获得该类实例对应的锁），从而有效避免了类成员变量的访问冲突（只要所有可能访问类成员变量的方法均被声明为 synchronized）。 

在 Java 中，不光是类实例，每一个类也对应一把锁，这样我们也可将类的静态成员函数声明为 synchronized ，以控制其对类的静态成员变量的访问。 

synchronized 方法的缺陷：若将一个大的方法声明为synchronized 将会大大影响效率，典型地，若将线程类的方法 run() 声明为 synchronized ，由于在线程的整个生命期内它一直在运行，因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中，将其声明为 synchronized ，并在主方法中调用来解决这一问题，但是 Java 为我们提供了更好的解决办法，那就是 synchronized 块。 

2. synchronized 块：通过 synchronized关键字来声明synchronized 块。语法如下： 


synchronized(syncObject)
{ 
//允许访问控制的代码 
}
 

synchronized 块是这样一个代码块，其中的代码必须获得对象 syncObject （如前所述，可以是类实例或类）的锁方能执行，具体机制同前所述。由于可以针对任意代码块，且可任意指定上锁的对象，故灵活性较高。 

六、线程的阻塞 

为了解决对共享存储区的访问冲突，Java 引入了同步机制，现在让我们来考察多个线程对共享资源的访问，显然同步机制已经不够了，因为在任意时刻所要求的资源不一定已经准备好了被访问，反过来，同一时刻准备好了的资源也可能不止一个。为了解决这种情况下的访问控制问题，Java 引入了对阻塞机制的支持。 

阻塞指的是暂停一个线程的执行以等待某个条件发生（如某资源就绪），学过操作系统的同学对它一定已经很熟悉了。Java 提供了大量方法来支持阻塞，下面让我们逐一分析。 

1. sleep() 方法：sleep() 允许 指定以毫秒为单位的一段时间作为参数，它使得线程在指定的时间内进入阻塞状态，不能得到CPU 时间，指定的时间一过，线程重新进入可执行状态。典型地，sleep() 被用在等待某个资源就绪的情形：测试发现条件不满足后，让线程阻塞一段时间后重新测试，直到条件满足为止。 

2. suspend() 和 resume() 方法：两个方法配套使用，suspend()使得线程进入阻塞状态，并且不会自动恢复，必须其对应的resume() 被调用，才能使得线程重新进入可执行状态。典型地，suspend() 和 resume() 被用在等待另一个线程产生的结果的情形：测试发现结果还没有产生后，让线程阻塞，另一个线程产生了结果后，调用 resume() 使其恢复。 

3. yield() 方法：yield() 使得线程放弃当前分得的 CPU 时间，但是不使线程阻塞，即线程仍处于可执行状态，随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程。 

4. wait() 和 notify() 方法：两个方法配套使用，wait() 使得线程进入阻塞状态，它有两种形式，一种允许 指定以毫秒为单位的一段时间作为参数，另一种没有参数，前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态，后者则必须对应的 notify() 被调用。 

初看起来它们与 suspend() 和 resume() 方法对没有什么分别，但是事实上它们是截然不同的。区别的核心在于，前面叙述的所有方法，阻塞时都不会释放占用的锁（如果占用了的话），而这一对方法则相反。 

上述的核心区别导致了一系列的细节上的区别。 

首先，前面叙述的所有方法都隶属于 Thread 类，但是这一对却直接隶属于 Object 类，也就是说，所有对象都拥有这一对方法。初看起来这十分不可思议，但是实际上却是很自然的，因为这一对方法阻塞时要释放占用的锁，而锁是任何对象都具有的，调用任意对象的 wait() 方法导致线程阻塞，并且该对象上的锁被释放。 

而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞（但要等到获得锁后才真正可执行）。 

其次，前面叙述的所有方法都可在任何位置调用，但是这一对方法却必须在 synchronized 方法或块中调用，理由也很简单，只有在synchronized 方法或块中当前线程才占有锁，才有锁可以释放。 

同样的道理，调用这一对方法的对象上的锁必须为当前线程所拥有，这样才有锁可以释放。因此，这一对方法调用必须放置在这样的 synchronized 方法或块中，该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件，则程序虽然仍能编译，但在运行时会出现IllegalMonitorStateException 异常。 

wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用，将它们和操作系统的进程间通信机制作一个比较就会发现它们的相似性：synchronized方法或块提供了类似于操作系统原语的功能，它们的执行不会受到多线程机制的干扰，而这一对方法则相当于 block 和wakeup 原语（这一对方法均声明为 synchronized）。 

它们的结合使得我们可以实现操作系统上一系列精妙的进程间通信的算法（如信号量算法），并用于解决各种复杂的线程间通信问题。关于 wait() 和 notify() 方法最后再说明两点： 

第一：调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的，我们无法预料哪一个线程将会被选择，所以编程时要特别小心，避免因这种不确定性而产生问题。 

第二：除了 notify()，还有一个方法 notifyAll() 也可起到类似作用，唯一的区别在于，调用 notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然，只有获得锁的那一个线程才能进入可执行状态。 

谈到阻塞，就不能不谈一谈死锁，略一分析就能发现，suspend() 方法和不指定超时期限的 wait() 方法的调用都可能产生死锁。遗憾的是，Java 并不在语言级别上支持死锁的避免，我们在编程中必须小心地避免死锁。 

以上我们对 Java 中实现线程阻塞的各种方法作了一番分析，我们重点分析了 wait() 和 notify()方法，因为它们的功能最强大，使用也最灵活，但是这也导致了它们的效率较低，较容易出错。实际使用中我们应该灵活使用各种方法，以便更好地达到我们的目的。 

七、守护线程 

守护线程是一类特殊的线程，它和普通线程的区别在于它并不是应用程序的核心部分，当一个应用程序的所有非守护线程终止运行时，即使仍然有守护线程在运行，应用程序也将终止，反之，只要有一个非守护线程在运行，应用程序就不会终止。守护线程一般被用于在后台为其它线程提供服务。 

可以通过调用方法 isDaemon() 来判断一个线程是否是守护线程，也可以调用方法 setDaemon() 来将一个线程设为守护线程。 

八、线程组 

线程组是一个 Java 特有的概念，在 Java 中，线程组是类ThreadGroup 的对象，每个线程都隶属于唯一一个线程组，这个线程组在线程创建时指定并在线程的整个生命期内都不能更改。 

你可以通过调用包含 ThreadGroup 类型参数的 Thread 类构造函数来指定线程属的线程组，若没有指定，则线程缺省地隶属于名为 system 的系统线程组。 

在 Java 中，除了预建的系统线程组外，所有线程组都必须显式创建。在 Java 中，除系统线程组外的每个线程组又隶属于另一个线程组，你可以在创建线程组时指定其所隶属的线程组，若没有指定，则缺省地隶属于系统线程组。这样，所有线程组组成了一棵以系统线程组为根的树。 

Java 允许我们对一个线程组中的所有线程同时进行操作，比如我们可以通过调用线程组的相应方法来设置其中所有线程的优先级，也可以启动或阻塞其中的所有线程。 

Java 的线程组机制的另一个重要作用是线程安全。线程组机制允许我们通过分组来区分有不同安全特性的线程，对不同组的线程进行不同的处理，还可以通过线程组的分层结构来支持不对等安全措施的采用。 

Java 的 ThreadGroup 类提供了大量的方法来方便我们对线程组树中的每一个线程组以及线程组中的每一个线程进行操作。 

九、总结 

在本文中，我们讲述了 Java 多线程编程的方方面面，包括创建线程，以及对多个线程进行调度、管理。我们深刻认识到了多线程编程的复杂性，以及线程切换开销带来的多线程程序的低效性，这也促使我们认真地思考一个问题：我们是否需要多线程？何时需要多线程？ 

多线程的核心在于多个代码块并发执行，本质特点在于各代码块之间的代码是乱序执行的。我们的程序是否需要多线程，就是要看这是否也是它的内在特点。 

假如我们的程序根本不要求多个代码块并发执行，那自然不需要使用多线程；假如我们的程序虽然要求多个代码块并发执行，但是却不要求乱序，则我们完全可以用一个循环来简单高效地实现，也不需要使用多线程；只有当它完全符合多线程的特点时，多线程机制对线程间通信和线程管理的强大支持才能有用武之地，这时使用多线程才是值得的。 

 来自：开发者在线
另外如果你喜欢电脑的话，我推荐你去初学者之路看看~</pre></div></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/380944.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-06-17 01:41 <a href="http://www.blogjava.net/stevenjohn/archive/2012/06/17/380944.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java多线程 sleep()和wait()的区别</title><link>http://www.blogjava.net/stevenjohn/archive/2012/06/17/380941.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Sat, 16 Jun 2012 17:15:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/06/17/380941.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/380941.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/06/17/380941.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/380941.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/380941.html</trackback:ping><description><![CDATA[<p>这两个方法主要来源是，sleep用于线程控制，而wait用于线程间的通信，与wait配套的方法还有notify和notifyAll.</p>
<p>区别一：</p>
<p>sleep是Thread类的方法，是线程用来 控制自身流程的，比如有一个要报时的线程，每一秒中打印出一个时间，那么我就需要在print方法前面加上一个sleep让自己每隔一秒执行一次。就像个闹钟一样。</p>
<p>wait是Object类的方法，用来线程间的通信，这个方法会使当前拥有该对象锁的进程等待知道其他线程调用notify方法时再醒来，不过你也可以给他指定一个时间，自动醒来。这个方法主要是用走不同线程之间的调度的。</p>
<p>区别二 ：</p>
<p>关于锁的释放 ，在这里假设大家已经知道了锁的概念及其意义。调用sleep方法不会释放锁（自己的感觉是sleep方法本来就是和锁没有关系的，因为他是一个线程用于管理自己的方法，不涉及线程通信）</p>
<p>JDK 7 中的解释：</p>
<p>&#8220;public static void sleep(long millis)</p>
<p>throws InterruptedException<br />Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers.The thread does not lose ownership of any monitors.</p>
<p>public final void wait() throws InterruptedException<br />Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.&#8220;<br />调用wait方法会释放当前线程的锁（其实线程间的通信是靠对象来管理的，所有操作一个对象的线程是这个对象通过自己的wait方法来管理的，就好像这个对象是电视机，三个人是三个线程，那么电视机的遥控器就是这个锁，假如现在A拿着遥控器，电视机调用wait方法，那么A就交出自己的遥控器，由jVM虚拟机调度，遥控器该交给谁。）【我想到一个好玩的例子：如果A拿遥控器的期间，他可以用自己的sleep每隔十分钟调一次电视台，而在他调台休息的十分钟期间，遥控器还在他的手上~】</p>
<p>区别三：</p>
<p>使用区域</p>
<p>由于wait函数的特殊意义，所以他是应该放在同步语句块中的，这样才有意义 。</p>
<p>注意：两个方法都需要抛出异常</p>
<p>个人见解：有sleep和wait的第二个区别，引起了我对Java线程机制的一个疑问，目前还没有看过JDk这方面的源码（其实看了，是木有看懂），线程的同步管理，是不是由对象在调度，如果是对象在调度，那么JDK 1.5新引入的ReentrantLock机制就比synchronized关键字更值得提倡。因为他更能反映出这么一个机制来。好多人不能理解wait和sleep的区别，我认为就是因为synchronized关键字的影响。当然自己还不懂JAVA的线程具体实现，留作疑问以后有时间继续研究吧</p><br /><br /><br /><br />
<div id="blog_content" class="blog_content">
<p><span style="font-size: small"><font size="2"><span style="color: #0000ff">Java中的多线程是一种<strong><span style="color: #800080">抢占式的机制</span> </strong>而不是分时机制。抢占式机制指的是有多个线程处于可运行状态，但是只有一个线程在运行。</span> <br /><br /></font><font size="3"><span style="font-size: medium"><strong><span style="color: #0000ff">共同点：</span> </strong></span><br /></font><font size="2">1. 他们都是在多线程的环境下，都可以在程序的调用处阻塞指定的毫秒数，并返回。<br /><br />2. wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态，从而使线程立刻抛出InterruptedException。<br />&nbsp;&nbsp; 如果线程A希望立即结束线程B，则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep /join，则线程B会立刻抛出InterruptedException，在catch() {} 中直接return即可安全地结束线程。<br />&nbsp;&nbsp; 需要注意的是，InterruptedException是线程自己从内部抛出的，并不是interrupt()方法抛出的。对某一线程调用 interrupt()时，如果该线程正在执行普通的代码，那么该线程根本就不会抛出InterruptedException。但是，一旦该线程进入到 wait()/sleep()/join()后，就会立刻抛出InterruptedException。<br /><br /></font><font size="3"><span style="font-size: medium"><strong><span style="color: #0000ff">不同点：</span> </strong></span><br /></font><font size="2">1. Thread类的方法：sleep(),yield()等<br />&nbsp;&nbsp; Object的方法：wait()和notify()等<br />&nbsp;&nbsp; <br />2. 每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互，来实现线程的同步。<br />&nbsp;&nbsp; sleep方法没有释放锁，而wait方法释放了锁，使得其他线程可以使用同步控制块或者方法。<br /><br />3. wait，notify和notifyAll只能在同步控制方法或者同步控制块里面使用，而sleep可以在任何地方使用<br />4. sleep必须捕获异常，而wait，notify和notifyAll不需要捕获异常&nbsp;&nbsp;&nbsp; </font></span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: medium"><font size="3"><strong>&nbsp;线程的调度 <br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 线程调度器按线程的优先级高低选择高优先级线程（进入运行中状态）执行，同时线程调度是抢先式调度，即如果在当前线程执行过程中，一个更高优先级的线程进入可运行状态，则这个线程立即被调度执行。 </font></span></p>
<p><span style="font-size: medium"><br /><font size="3">抢先式调度又分为：时间片方式和独占方式。在时间片方式下，当前活动线程执行完当前时间片后，如果有其他处于就绪状态的相同优先级的线程，系统会将执行权交给其他就绪态的同优先级线程；当前活动线程转入等待执行队列，等待下一个时间片的调度。 <br />在独占方式下，当前活动线程一旦获得执行权，将一直执行下去，直到执行完毕或由于某种原因主动放弃CPU，或者是有一高优先级的线程处于就绪状态。</font></span></p></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/380941.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-06-17 01:15 <a href="http://www.blogjava.net/stevenjohn/archive/2012/06/17/380941.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java  多线程</title><link>http://www.blogjava.net/stevenjohn/archive/2012/06/06/380126.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Wed, 06 Jun 2012 06:19:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/06/06/380126.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/380126.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/06/06/380126.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/380126.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/380126.html</trackback:ping><description><![CDATA[<!--StartFragment -->


<div>sleep,wait,suspend,resume,join,interrupt,stop,destory<br /></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/380126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-06-06 14:19 <a href="http://www.blogjava.net/stevenjohn/archive/2012/06/06/380126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>进程和线程之间的区别和联系</title><link>http://www.blogjava.net/stevenjohn/archive/2012/05/22/378842.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Tue, 22 May 2012 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2012/05/22/378842.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/378842.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2012/05/22/378842.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/378842.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/378842.html</trackback:ping><description><![CDATA[<pre id="content-46240341" class="reply-text mb10">进程和程序区别和联系表现在以下方面：
1)程序只是一组指令的有序集合，它本身没有任何运行的含义，它只是
 一个静态的实体。而进程则不同，它是程序在某个数据集上的执行。
 进程是一个动态的实体，它有自己的生命周期。它因创建而产生，因
 调度而运行，因等待资源或事件而被处于等待状态，因完成任务而被
 撤消。反映了一个程序在一定的数据集上运行的全部动态过程。
2)进程和程序并不是一一对应的，一个程序执行在不同的数据集上就成
 为不同的进程，可以用进程控制块来唯一地标识每个进程。而这一点
 正是程序无法做到的，由于程序没有和数据产生直接的联系，既使是
 执行不同的数据的程序，他们的指令的集合依然是一样的，所以无法
 唯一地标识出这些运行于不同数据集上的程序。一般来说，一个进程
 肯定有一个与之对应的程序，而且只有一个。而一个程序有可能没有
 与之对应的进程(因为它没有执行),也有可能有多个进程与之对应(运
 行在几个不同的数据集上)。
3)进程还具有并发性和交往性，这也与程序的封闭性不同。
----------------------------------------------------------------------------------------------

进程和线程都是由操作系统所体会的程序运行的基本单元，系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于：

简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 
线程的划分尺度小于进程，使得多线程程序的并发性高。
另外，进程在执行过程中拥有独立的内存单元，而多个线程共享内存，从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行，必须依存在应用程序中，由应用程序提供多个线程执行控制。
从逻辑角度来看，多线程的意义在于一个应用程序中，有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用，来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

----------------------------------------------------------------------------------------------

进程和线程的区别 
 
说法一：进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行

 

说法二：进程和线程都是由操作系统所体会的程序运行的基本单元，系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于：

简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 

线程的划分尺度小于进程，使得多线程程序的并发性高。

另外，进程在执行过程中拥有独立的内存单元，而多个线程共享内存，从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行，必须依存在应用程序中，由应用程序提供多个线程执行控制。

从逻辑角度来看，多线程的意义在于一个应用程序中，有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用，来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

 

说法三：多线程共存于应用程序中是现代操作系统中的基本特征和重要标志。用过UNIX操作系统的读者知道进程，在UNIX操作系统中，每个应用程序的执行都在操作系统内核中登记一个进程标志，操作系统根据分配的标志对应用程序的执行进行调度和系统资源分配，但进程和线程有什么区别呢？

进程和线程都是由操作系统所体会的程序运行的基本单元，系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于：

线程的划分尺度小于进程，使得多线程程序的并发性搞。

另外，进程在执行过程中拥有独立的内存单元，而多个线程共享内存，从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行，必须依存在应用程序中，由应用程序提供多个线程执行控制。

从逻辑角度来看，多线程的意义在于一个应用程序中，有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用，来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程（Process）是最初定义在Unix等多用户、多任务操作系统环境下用于表示应用程序在内存环境中基本执行单元的概念。以Unix操作系统为例，进程是Unix操作系统环境中的基本成分、是系统资源分配的基本单位。Unix操作系统中完成的几乎所有用户管理和资源分配等工作都是通过操作系统对应用程序进程的控制来实现的。 

C、C++、Java等语言编写的源程序经相应的编译器编译成可执行文件后，提交给计算机处理器运行。这时，处在可执行状态中的应用程序称为进程。从用户角度来看，进程是应用程序的一个执行过程。从操作系统核心角度来看，进程代表的是操作系统分配的内存、CPU时间片等资源的基本单位，是为正在运行的程序提供的运行环境。进程与应用程序的区别在于应用程序作为一个静态文件存储在计算机系统的硬盘等存储空间中，而进程则是处于动态条件下由操作系统维护的系统资源管理实体。多任务环境下应用程序进程的主要特点包括： 

&#9679;进程在执行过程中有内存单元的初始入口点，并且进程存活过程中始终拥有独立的内存地址空间； 

&#9679;进程的生存期状态包括创建、就绪、运行、阻塞和死亡等类型； 

&#9679;从应用程序进程在执行过程中向CPU发出的运行指令形式不同，可以将进程的状态分为用户态和核心态。处于用户态下的进程执行的是应用程序指令、处于核心态下的应用程序进程执行的是操作系统指令。 

在Unix操作系统启动过程中，系统自动创建swapper、init等系统进程，用于管理内存资源以及对用户进程进行调度等。在Unix环境下无论是由操作系统创建的进程还要由应用程序执行创建的进程，均拥有唯一的进程标识（PID）。 

说法四：应用程序在执行过程中存在一个内存空间的初始入口点地址、一个程序执行过程中的代码执行序列以及用于标识进程结束的内存出口点地址，在进程执行过程中的每一时间点均有唯一的处理器指令与内存单元地址相对应。 

Java语言中定义的线程（Thread）同样包括一个内存入口点地址、一个出口点地址以及能够顺序执行的代码序列。但是进程与线程的重要区别在于线程不能够单独执行，它必须运行在处于活动状态的应用程序进程中，因此可以定义线程是程序内部的具有并发性的顺序代码流。 

Unix操作系统和Microsoft Windows操作系统支持多用户、多进程的并发执行，而Java语言支持应用程序进程内部的多个执行线程的并发执行。多线程的意义在于一个应用程序的多个逻辑单元可以并发地执行。但是多线程并不意味着多个用户进程在执行，操作系统也不把每个线程作为独立的进程来分配独立的系统资源。进程可以创建其子进程，子进程与父进程拥有不同的可执行代码和数据内存空间。而在用于代表应用程序的进程中多个线程共享数据内存空间，但保持每个线程拥有独立的执行堆栈和程序执行上下文（Context）。 

基于上述区别，线程也可以称为轻型进程 (Light Weight Process，LWP)。不同线程间允许任务协作和数据交换，使得在计算机系统资源消耗等方面非常廉价。 

线程需要操作系统的支持，不是所有类型的计算机都支持多线程应用程序。Java程序设计语言将线程支持与语言运行环境结合在一起，提供了多任务并发执行的能力。这就好比一个人在处理家务的过程中，将衣服放到洗衣机中自动洗涤后将大米放在电饭锅里，然后开始做菜。等菜做好了，饭熟了同时衣服也洗好了。 

需要注意的是：在应用程序中使用多线程不会增加 CPU 的数据处理能力。只有在多CPU 的计算机或者在网络计算体系结构下，将Java程序划分为多个并发执行线程后，同时启动多个线程运行，使不同的线程运行在基于不同处理器的Java虚拟机中，才能提高应用程序的执行效率。 </pre>
<div class="reference mt10 gray" sizset="46" sizcache="12"><span class="refer-title">参考资料：</span><a href="http://gdshang.blogchina.com/3305743.html" target="_blank"><font color="#133db6">http://gdshang.blogchina.com/3305743.html</font></a> </div><img src ="http://www.blogjava.net/stevenjohn/aggbug/378842.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2012-05-22 15:19 <a href="http://www.blogjava.net/stevenjohn/archive/2012/05/22/378842.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>