CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
主要方法
public CountDownLatch(int count);
public void countDown();
public void await() throws InterruptedException
构造方法参数指定了计数的次数
countDown方法,当前线程调用此方法,则计数减一
awaint方法,调用此方法会一直阻塞当前线程,直到计时器的值为0
CountDownLatch 很适合用来将一个任务分为n个独立的部分,等这些部分都完成后继续接下来的任务,CountDownLatch 只能出发一次,计数值不能被重置。
CountDownLatch 是的实现原理是根据 继承类 AbstractQueuedSynchronizer 的doAcquireSharedInterruptibly(int arg)方法
CyclicBarrier 和 CountDownLatch 在用法上的不同
CountDownLatch 适用于一组线程和另一个主线程之间的工作协作。一个主线程等待一组工作线程的任务完毕才继续它的执行是使用 CountDownLatch 的主要场景;CyclicBarrier 用于一组或几组线程,比如一组线程需要在一个时间点上达成一致,例如同时开始一个工作。另外,CyclicBarrier 的循环特性和构造函数所接受的 Runnable 参数也是 CountDownLatch 所不具备的。
例子
/**
* 模拟项目的开发,只有当每个模块都完成后,项目才完成
* 每个模块的用时不同
*/
class Module implements Runnable{
private CountDownLatch latch;
private String moduleName;
private int time;//用时
public Module(CountDownLatch latch, String moduleName,int time) {
super();
this.latch = latch;
this.moduleName = moduleName;
this.time = time;
}
@Override
public void run() {
try {
work();
latch.countDown(); //对当前运行的线程减一
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void work() throws InterruptedException{
TimeUnit.MILLISECONDS.sleep(time);
System.out.println(moduleName + " 完成,耗时:" + time);
}
}
class Controller implements Runnable{
private CountDownLatch latch;
public Controller(CountDownLatch latch) {
super();
this.latch = latch;
}
@Override
public void run() {
try {
latch.await();
System.out.println("所有模块都完成,任务完成");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Project {
static final int SIZE = 20;
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(SIZE);
Random r = new Random();
ExecutorService exec = Executors.newCachedThreadPool();
Controller controller = new Controller(latch);
exec.execute(controller);
for(int i = 0; i < SIZE; i++){
exec.execute(new Module(latch, "模块" + (i + 1), r.nextInt(2000)));
}
exec.shutdown();
}
}