CountDownLatch是java同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给定的计数num赋予CountDownLatch的构造函数,表示需要同步这num个线程,当这些线程运行到同步点时,对CountDownLatch调用CountDown()方法,使得num-1,当num减为0时,表示所有需要同步的线程均到达同步点,此时被CountDownLatch的await()方法阻塞的线程开始执行。
CountDownLatch是闭锁的一种实现,闭锁是一种同步工具类,可以延迟线程的进度直到其到达终止状态。它的作用相当于一扇门:在闭锁到达结束状态之前,这扇门始终是关闭的,而且没有任何线程可以通过,当到达结束状态时,这扇门就会打开并允许所有的线程通过。当闭锁到达结束状态后,将不会再改变状态,因此这扇门将永远保持打开状态。闭锁可以用来确保某些活动都完成后才继续执行,比如:
1.确保某个计算在其需要的所有资源都被初始化之后才继续执行。二元闭锁(包括两个状态)可以用来表示“资源R已经被初始化”,而所有需要R的操作都必须在这个闭锁上等待。
2.确保某个服务在其依赖的所有其它服务都已经启动之后才启动。每个服务都有一个相关的二元闭锁。当启动服务s时,将首先在s依赖的其它服务的闭锁上等待,在所有依赖的服务都启动后会释放闭锁s,这样其它依赖s的服务才能继续执行。
3.等待直到某个操作的所有参与者(比如,在多玩家游戏中的所有玩家)都就绪再继续执行。在这种情况中,当所有玩家都准备就绪时,闭锁将到达结束状态。
下面是一个示例程序,这个程序计算四个数的和:
思路是把四个数分为两组,分别计算和,然后再对两组的和进行求和,代码如下:
package com.test; import java.util.concurrent.CountDownLatch; public class CountDownLatchTest { static class Worker extends Thread{ private CountDownLatch count; private int left; private int right; private int result; public Worker(CountDownLatch count, int left,int right) { this.count = count; this.left = left; this.right = right; } @Override public void run() { synchronized(count){ System.out.print(Thread.currentThread().getName()+" : "); result = left+right; System.out.println("Partial result: "+result); count.countDown(); } } public int getResult(){ return result; } } public static void main(String[] args) throws Exception { //计算1+2+3+4 CountDownLatch latch = new CountDownLatch(2); Worker worker = new Worker(latch,1,2); Worker worker2 = new Worker(latch,3,4); worker.start(); worker2.start(); System.out.println("Main waiting!!"); latch.await(); System.out.println("Waiting end,Result is: "+(worker.getResult()+worker2.getResult())); } }
使用FutureTask的代码:
package com.test; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; class Worker implements Callable<Integer> { private int hours = 12; private int amount; @Override public Integer call() throws Exception { while(hours>0){ amount++; System.out.println("I'm working......"+amount); hours--; Thread.sleep(100); } return amount; } } public class FutureTaskTest { public static void main(String[] args) { Worker worker = new Worker(); FutureTask<Integer> boss = new FutureTask<Integer>(worker); new Thread(boss).start(); //System.out.println("hello"); //System.out.println(boss.isDone()); while(!boss.isDone()){ try { System.out.println("看工人做完了没.........."); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } int amount; try{ amount = boss.get(); System.out.println("工作完成"+amount); }catch(InterruptedException e){ e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }