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();
}
}