本文将要介绍的内容都是Java5中的新特性,一个是倒计时记数器---CountDownLatch,另一个是用于线程间数据交换的Exchanger.
一.CountDownLatch
1.什么是CountDownLatch?
倒计时计数器,调用CountDownLatch对象的CountDown()方法就将计数器减一,当计数到达0时,则所有等待者或者全部等待者开始执行.
2.如何用?
new CountDownLatch(1);
直接new,其构造函数必须传一个int类型的参数,参数的意思是:
count the number of times countDown must be invoked before threads can pass through await
大致可理解成,有一个门,有N个门闩,要想打开门必须把所有门闩都打开,对应到线程上是说在线程通过等待前必须要执行的倒计时操作.
3.举例
package com.amos.concurrent; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @ClassName: Count_Down_Latch_Test * @Description: 倒计时学习 * @author: amosli * @email:hi_amos@outlook.com * @date Apr 27, 2014 11:51:43 PM */ public class Count_Down_Latch_Test { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); final CountDownLatch countdownOrder = new CountDownLatch(1);// an order final CountDownLatch countdownAnwser = new CountDownLatch(3);// anwser for (int i = 0; i < 3; i++) { Runnable runnable = new Runnable() { public void run() { try { countdownOrder.await(); System.out.println("线程" + Thread.currentThread().getName() + " 正准备接受命令"); System.out.println("线程"+Thread.currentThread().getName()+" 已经接受命令!"); Thread.sleep(new Random().nextInt(1000)); System.out.println("线程"+Thread.currentThread().getName()+" 回应处理结果!"); countdownAnwser.countDown(); } catch (Exception e) { e.printStackTrace(); } } }; executorService.execute(runnable);//启动线程池 } try { Thread.sleep(new Random().nextInt(1000)); System.out.println("线程"+Thread.currentThread().getName()+" 即将下达命令!!"); countdownOrder.countDown(); System.out.println("线程"+Thread.currentThread().getName()+" 已经下达命令,正在等待返回结果!"); countdownAnwser.await(); System.out.println("线程"+Thread.currentThread().getName()+" 已经收到所有处理结果!"); } catch (InterruptedException e) { e.printStackTrace(); } } }
1).效果如下图所示:
2)程序说明
首先是创建了一个可缓存的线程池--->接着,创建两个CountDownLatch类,一个赋值为1,一个赋值为3;----->然后,执行一个for循环,在循环中,首先是实现了一个Runnable接口,然后,将Runnable接口加入到线程池中; 其中Runnable接口,首先是等待计数器为0,然后如果为0那么将计数器2的值减一,每循环一次减一,当第三次循环时,线程执行完毕;----->在Runnable接口中等待计数器为0,整个程序无法向下走,这时main方法,即主线程执行CountDown方法,计数器减一-------->最后等待所有的线程都执行完毕,返回最终的结果.
4.扩展--官方例子
package com.amos.concurrent; import java.util.concurrent.CountDownLatch; public class CountDownLatchTest { public static void main(String[] args) { try { new CountDownLatchTest().new Driver().main(); } catch (InterruptedException e) { e.printStackTrace(); } } class Driver { // ... void main() throws InterruptedException { CountDownLatch startSignal = new CountDownLatch(1); CountDownLatch doneSignal = new CountDownLatch(3); for (int i = 0; i < 3; ++i) // create and start threads new Thread(new worker(startSignal, doneSignal)).start(); dosomethingelse(); // don't let run yet startSignal.countDown(); // let all threads proceed dosomethingelse(); doneSignal.await(); // wait for all to finish } private void dosomethingelse() { System.out.println("dosomethingelse..."); } } class worker implements Runnable { private final CountDownLatch startsignal; private final CountDownLatch donesignal; worker(CountDownLatch startsignal, CountDownLatch donesignal) { this.startsignal = startsignal; this.donesignal = donesignal; } public void run() { try { startsignal.await(); dowork(); donesignal.countDown(); } catch (Exception ex) { } // return; } void dowork() { System.out.println("dowork...."); } } }