﻿<?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-巷尾的酒吧-随笔分类-thread</title><link>http://www.blogjava.net/abin/category/52780.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 19 Oct 2012 22:45:41 GMT</lastBuildDate><pubDate>Fri, 19 Oct 2012 22:45:41 GMT</pubDate><ttl>60</ttl><item><title>java中的volatile和synchronized</title><link>http://www.blogjava.net/abin/archive/2012/10/19/389867.html</link><dc:creator>abing</dc:creator><author>abing</author><pubDate>Fri, 19 Oct 2012 05:36:00 GMT</pubDate><guid>http://www.blogjava.net/abin/archive/2012/10/19/389867.html</guid><wfw:comment>http://www.blogjava.net/abin/comments/389867.html</wfw:comment><comments>http://www.blogjava.net/abin/archive/2012/10/19/389867.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/abin/comments/commentRss/389867.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/abin/services/trackbacks/389867.html</trackback:ping><description><![CDATA[<p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">这个可能是最好的对比volatile&nbsp;和synchronized&nbsp;作用的文章了。volatile&nbsp;是一个变量修饰符，而synchronized&nbsp;是一个方法或块的修饰符。所以我们使用这两种关键字来指定三种简单的存取变量的方式。</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;int i1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int geti1() {return i1;}</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">volatile int i2;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int geti2() {return i2;}</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; text-indent: 18pt; "><span style="font-size: 9pt; font-family: 宋体; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i3;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;synchronized int geti3() {return i3;}</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">geti1()</span>&nbsp;<span style="font-size: 9pt; font-family: 宋体; ">在<strong>当前线程</strong>&nbsp;中立即获取在i1&nbsp;变量中的值。线程可以获得变量的本地拷贝，而所获得的变量的值并不一定与其他线程所获得的值相同。特别是，如果其他的线程修改了i1&nbsp;的值，那么当前线程获得的i1&nbsp;的值可能与修改后的值有所差别。实际上，Java&nbsp;有一种主内存的机制，使用一个主内存来保存变量当前的正确的值。线程将变量的值拷贝到自己独立的内存中，而这些线程的内存拷贝可能与主内存中的值不同。所以实际当中可能发生这样的情况，在主内存中i1&nbsp;的值为1&nbsp;，线程1&nbsp;和线程2&nbsp;都更改了i1&nbsp;，但是却没把更新的值传回给主内存或其他线程中，那么可能在线程1&nbsp;中i1&nbsp;的值为2，线程2&nbsp;中i1&nbsp;的值却为&nbsp;3&nbsp;。</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">另一方面，geti2()&nbsp;可以有效的从主内存中获取i2&nbsp;的值。一个volatile&nbsp;类型的变量不允许线程从主内存中将变量的值拷贝到自己的存储空间。因此，一个声明为volatile&nbsp;类型的变量将在所有的线程中同步的获得数据，不论你在任何线程中更改了变量，其他的线程将立即得到同样的结果。由于线程存取或更改自己的数据拷贝有更高的效率，所以volatile&nbsp;类型变量在性能上有所消耗。</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">那么如果volatile&nbsp;变量已经可以使数据在线程间同步，那么synchronizes&nbsp;用来干什么呢？两者有两方面的不同。首先，synchronized&nbsp;获取和释放由监听器控制的锁，如果两个线程都使用一个监听器(&nbsp;即相同对象锁)&nbsp;，那么监听器可以强制在一个时刻只有一个线程能处理代码块，这是最一般的同步。另外，synchronized&nbsp;还能使内存同步。在实际当中，synchronized&nbsp;使得所有的线程内存与主内存相同步。所以geti3()&nbsp;的执行过程如下：</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">1.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 9pt; font-family: 宋体; ">线程从监听器获取对象的锁。(&nbsp;这里假设监听器非锁，否则线程只有等到监听器解锁才能获取对象锁)</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">2.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 9pt; font-family: 宋体; ">线程内存更新<strong>所有</strong>&nbsp;的变量，也就是说他将读取主内存中的变量使自己的变量保证有效。(JVM&nbsp;会使用一个&#8220;脏&#8221;标志来最优化过程，使得仅仅具有&#8220;脏&#8221;标志变量被更新。详细的情况查询JAVA规范的17.9)</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">3.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 9pt; font-family: 宋体; ">代码块被执行(&nbsp;在这个例子中，设置返回值为刚刚从主内存重置的i3&nbsp;当前的值。)</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">4.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 9pt; font-family: 宋体; ">任何变量的变更将被写回到主内存中。但是这个例子中geti3()&nbsp;没有什么变化。</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">5.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 9pt; font-family: 宋体; ">线程释放对象的锁给监听器。</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">所以volatile&nbsp;只能在线程内存和主内存之间同步一个变量的值，而synchronized&nbsp;则同步在线程内存和主内存之间的所有变量的值，并且通过锁住和释放监听器来实现。显然，synchronized&nbsp;在性能上将比volatile&nbsp;更加有所消耗。</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; ">&nbsp;</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; "><span style="font-size: 9pt; font-family: 宋体; ">=============关于两者的区别===================</span></p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; ">1.volatile本质是在告诉jvm当前变量在寄存器（工作内存）中的值是不确定的，需要从主存中读取；synchronized则是锁定当前变量，只有当前线程可以访问该变量，其他线程被阻塞住。&nbsp;<br />2.volatile仅能使用在变量级别；synchronized则可以使用在变量、方法、和类级别的&nbsp;<br />3.<span style="color: #ff0000; ">volatile仅能实现变量的修改可见性，不能保证原子性</span>&nbsp;；而synchronized则可以保证变量的修改可见性和原子性&nbsp;<br />4.volatile不会造成线程的阻塞；synchronized可能会造成线程的阻塞。&nbsp;<br />5.volatile标记的变量不会被编译器优化；synchronized标记的变量可以被编译器优化</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; ">&nbsp;</p><p align="left" style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff; ">红字体部分的原因如下：<br />线程A修改了变量还没结束时,另外的线程B可以看到已修改的值,而且可以修改这个变量,而不用等待A释放锁,因为Volatile 变量没上锁</p><img src ="http://www.blogjava.net/abin/aggbug/389867.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/abin/" target="_blank">abing</a> 2012-10-19 13:36 <a href="http://www.blogjava.net/abin/archive/2012/10/19/389867.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 死锁</title><link>http://www.blogjava.net/abin/archive/2012/10/17/389745.html</link><dc:creator>abing</dc:creator><author>abing</author><pubDate>Wed, 17 Oct 2012 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/abin/archive/2012/10/17/389745.html</guid><wfw:comment>http://www.blogjava.net/abin/comments/389745.html</wfw:comment><comments>http://www.blogjava.net/abin/archive/2012/10/17/389745.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/abin/comments/commentRss/389745.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/abin/services/trackbacks/389745.html</trackback:ping><description><![CDATA[<pre id="best-answer-content"  mb10"="" data-accusearea="aContent">死锁     死锁是这样一种情形：多个线程同时被阻塞，它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞，因此程序不可能正常终止。     导致死锁的根源在于不适当地运用&#8220;synchronized&#8221;关键词来管理线程对特定对象的访问。&#8220;synchronized&#8221;关键词的作用是，确保在某个时刻只有一个线程被允许执行特定的代码块，因此，被允许执行的线程首先必须拥有对变量或对象的排他性的访问权。当线程访问对象时，线程会给对象加锁，而这个锁导致其它也想访问同一对象的线程被阻塞，直至第一个线程释放它加在对象上的锁。     由于这个原因，在使用&#8220;synchronized&#8221;关键词时，很容易出现两个线程互相等待对方做出某个动作的情形。代码一是一个导致死锁的简单例子。   //代码一 class Deadlocker {  int field_1;  private Object lock_1 = new int[1];  int field_2;  private Object lock_2 = new int[1];   public void method1(int value) {   &#8220;synchronized&#8221; (lock_1) {    &#8220;synchronized&#8221; (lock_2) {     field_1 = 0; field_2 = 0;    }   }  }   public void method2(int value) {   &#8220;synchronized&#8221; (lock_2) {    &#8220;synchronized&#8221; (lock_1) {     field_1 = 0; field_2 = 0;    }   }  } }       参考代码一，考虑下面的过程：     &#9670; 一个线程（ThreadA）调用method1()。     &#9670; ThreadA在lock_1上同步，但允许被抢先执行。     &#9670; 另一个线程（ThreadB）开始执行。     &#9670; ThreadB调用method2()。     &#9670; ThreadB获得lock_2，继续执行，企图获得lock_1。但ThreadB不能获得lock_1，因为ThreadA占有lock_1。     &#9670; 现在，ThreadB阻塞，因为它在等待ThreadA释放lock_1。     &#9670; 现在轮到ThreadA继续执行。ThreadA试图获得lock_2，但不能成功，因为lock_2已经被ThreadB占有了。     &#9670; ThreadA和ThreadB都被阻塞，程序死锁。     当然，大多数的死锁不会这么显而易见，需要仔细分析代码才能看出，对于规模较大的多线程程序来说尤其如此。好的线程分析工具，例如JProbe Threadalyzer能够分析死锁并指出产生问题的代码位置。     隐性死锁     隐性死锁由于不规范的编程方式引起，但不一定每次测试运行时都会出现程序死锁的情形。由于这个原因，一些隐性死锁可能要到应用正式发布之后才会被发现，因此它的危害性比普通死锁更大。下面介绍两种导致隐性死锁的情况：加锁次序和占有并等待。     加锁次序     当多个并发的线程分别试图同时占有两个锁时，会出现加锁次序冲突的情形。如果一个线程占有了另一个线程必需的锁，就有可能出现死锁。考虑下面的情形，ThreadA和ThreadB两个线程分别需要同时拥有lock_1、lock_2两个锁，加锁过程可能如下：     &#9670; ThreadA获得lock_1；     &#9670; ThreadA被抢占，VM调度程序转到ThreadB；     &#9670; ThreadB获得lock_2；     &#9670; ThreadB被抢占，VM调度程序转到ThreadA；     &#9670; ThreadA试图获得lock_2，但lock_2被ThreadB占有，所以ThreadA阻塞；     &#9670; 调度程序转到ThreadB；     &#9670; ThreadB试图获得lock_1，但lock_1被ThreadA占有，所以ThreadB阻塞；     &#9670; ThreadA和ThreadB死锁。     必须指出的是，在代码丝毫不做变动的情况下，有些时候上述死锁过程不会出现，VM调度程序可能让其中一个线程同时获得lock_1和lock_2两个锁，即线程获取两个锁的过程没有被中断。在这种情形下，常规的死锁检测很难确定错误所在。     占有并等待     如果一个线程获得了一个锁之后还要等待来自另一个线程的通知，可能出现另一种隐性死锁，考虑代码二。   //代码二 public class queue {  static java.lang.Object queueLock_;  Producer producer_;  Consumer consumer_;   public class Producer {   void produce() {    while (!done) {     &#8220;synchronized&#8221; (queueLock_) {      produceItemAndAddItToQueue();      &#8220;synchronized&#8221; (consumer_) {       consumer_.notify();      }     }    }   }    public class Consumer {    consume() {     while (!done) {      &#8220;synchronized&#8221; (queueLock_) {       &#8220;synchronized&#8221; (consumer_) {        consumer_.wait();       }       removeItemFromQueueAndProcessIt();      }     }    }   }  } }       在代码二中，Producer向队列加入一项新的内容后通知Consumer，以便它处理新的内容。问题在于，Consumer可能保持加在队列上的锁，阻止Producer访问队列，甚至在Consumer等待Producer的通知时也会继续保持锁。这样，由于Producer不能向队列添加新的内容，而Consumer却在等待Producer加入新内容的通知，结果就导致了死锁。     在等待时占有的锁是一种隐性的死锁，这是因为事情可能按照比较理想的情况发展&#8212;Producer线程不需要被Consumer占据的锁。尽管如此，除非有绝对可靠的理由肯定Producer线程永远不需要该锁，否则这种编程方式仍是不安全的。有时&#8220;占有并等待&#8221;还可能引发一连串的线程等待，例如，线程A占有线程B需要的锁并等待，而线程B又占有线程C需要的锁并等待等。     要改正代码二的错误，只需修改Consumer类，把wait()移出&#8220;synchronized&#8221;()即可。</pre> <div mt10"="" data-accusearea="aRefer" sizcache="15" sizset="48">参考资料：<span sizcache="15" sizset="48"><a href="http://software.ccidnet.com/art/322/20030410/43222_1.html" target="_blank">http://software.ccidnet.com/art/322/20030410/43222_1.html</a></span></div><img src ="http://www.blogjava.net/abin/aggbug/389745.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/abin/" target="_blank">abing</a> 2012-10-17 15:48 <a href="http://www.blogjava.net/abin/archive/2012/10/17/389745.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 三种方式实现多线程</title><link>http://www.blogjava.net/abin/archive/2012/10/12/389494.html</link><dc:creator>abing</dc:creator><author>abing</author><pubDate>Fri, 12 Oct 2012 15:43:00 GMT</pubDate><guid>http://www.blogjava.net/abin/archive/2012/10/12/389494.html</guid><wfw:comment>http://www.blogjava.net/abin/comments/389494.html</wfw:comment><comments>http://www.blogjava.net/abin/archive/2012/10/12/389494.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/abin/comments/commentRss/389494.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/abin/services/trackbacks/389494.html</trackback:ping><description><![CDATA[<div>第一种：（Thread）<br /> <p>package com.abin.lee.servlet.mythread.thread;</p> <p>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 /><br />测试代码：<br /> <p>package com.abin.lee.servlet.mythread.thread;</p> <p>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>}<br /></p><br /><br /><br />第二种：（Runnable）<br /> <p>package com.abin.lee.servlet.mythread.runnable;</p> <p>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 /><br /><br />测试代码：<br /> <p>package com.abin.lee.servlet.mythread.runnable;</p> <p>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 /><br /><br />第三种：（Callable）这种说明一下，这个实现多线程的方式是在JDK1.5引进的，在java.util.concurrent.Callable&nbsp;  这个并发包下面，并且提供同步返回结果的多线程。<br /> <p>package com.abin.lee.servlet.mythread.callable;</p> <p>import java.util.concurrent.Callable;<br />import  java.util.concurrent.locks.Lock;<br />import  java.util.concurrent.locks.ReentrantLock;</p> <p>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 /><br />&nbsp;&nbsp;&nbsp;return  result;<br />&nbsp;&nbsp;<br />&nbsp;}<br />&nbsp;<br />}<br /></p><br /><br /><br />测试代码：<br /> <p>package com.abin.lee.servlet.mythread.callable;</p> <p>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>import org.junit.Test;</p> <p>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>}<br /><br />测试结果：<br /></p><div>开始时间：1350056647659,线程名字：pool-1-thread-1</div><div>name=ManyThread</div><div>结束时间：1350056650661,线程名字：pool-1-thread-1</div><div>future1=success</div><div>开始时间：1350056650661,线程名字：pool-1-thread-2</div><div>name=ManyThread</div><div>结束时间：1350056653661,线程名字：pool-1-thread-2</div><div>future2=success</div><div>开始时间：1350056653662,线程名字：pool-1-thread-3</div><div>name=ManyThread</div><div>结束时间：1350056656663,线程名字：pool-1-thread-3</div><div>future3=success</div><div></div><p>&nbsp;</p></div><img src ="http://www.blogjava.net/abin/aggbug/389494.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/abin/" target="_blank">abing</a> 2012-10-12 23:43 <a href="http://www.blogjava.net/abin/archive/2012/10/12/389494.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>