CountDownLatch
- 用来同步一个或多个任务,强制它们等待由其他任务执行的一组操作完成。
- 可以向CountDownLatch对象设置一个初始计数值,任何在这个对象上调用wait()的方法都将阻塞,直至这个计数值到达0。其他任务在结束其工作时,可以在该对象上调用countDown()来减小这个计数值。CountDownLathc被设计为只触发一次,计数值不能被重置。如果需要能够重置计数值的版本,可以使用CyclicBarrier。
- 调用countDown()的任务在产生这个调用时并没有被阻塞,只有对await的调用会被阻塞,直至计数值达到0。
- CountDownLatch的典型用法是:将一个程序分为n个互相独立的可解决任务,并创建值为0的CountDownLatch。当每个任务完成时,都会在这个锁存器上调用countDown()。等待问题别解决的任务在这个锁存器上调用await(),将它们自己拦住,直至锁存器技术结束。
package com21concurrent;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Created by Panda on 2018/6/1.
*/
class TaskPortion implements Runnable{
private static int counter=0;
private final int id=counter++;
private static Random random = new Random(47);
private final CountDownLatch countDownLatch;
public TaskPortion(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try{
doWork();
countDownLatch.countDown();
System.out.println(countDownLatch.getCount());
}catch (InterruptedException e){
}
}
public void doWork() throws InterruptedException{
TimeUnit.MILLISECONDS.sleep(random.nextInt(2000));
System.out.println(this+"completed");
}
public String toString(){
return String.format("%1$-3d ",id);
}
}
class WaitingTask implements Runnable{
private static int counter=0;
private final int id=counter++;
private final CountDownLatch countDownLatch;
public WaitingTask(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try{
countDownLatch.await();
System.out.println(Thread.currentThread().getName());
System.out.println("Latch barrier passed for "+this);
}catch (InterruptedException e){
System.out.println(this+"interrupted");
}
}
public String toString(){
return String.format("WaitingTask %1$-3d",id);
}
}
public class CountDownLatchDemo {
static final int SIZE=100;
public static void main(String[] args) throws Exception{
ExecutorService executorService= Executors.newCachedThreadPool();
CountDownLatch countDownLatch = new CountDownLatch(SIZE);
for (int i = 0; i < 10; i++) {
executorService.execute(new WaitingTask(countDownLatch));
}
for (int i = 0; i <SIZE ; i++) {
executorService.execute(new TaskPortion(countDownLatch));
}
System.out.println("Launched all tasks");
executorService.shutdown();
}
}