CountDownLatch 可以立即看作一个计数器,不过计数是原子操作,也就是说同一时间只有一个线程能够操作该计数器;
我们先看看该类常用的几个方法:
你可以给它设定一个数目,调用该类await方法会使调用await的方法的线程处于等待状态;直到该计数器计数为0;由此特性,我们可以将它用于一下场景:
场景:只有把所有的任务执行完毕后才执行另外一个任务
下面演示是当把三个WorkTask任务都执行完毕后才执行AllTaskDonedTask任务
public class Test{
public static void main(String[] args) {
int taskSize = 3;
//创建一个计数器,并对其初始化
final CountDownLatch doneSingle = new CountDownLatch(taskSize);
//创建一个固定线程池,此处线程池的线程数目和taskSize无直接关
Executor executor = Executors.newFixedThreadPool(taskSize);
//执行所有任务
for (int i = 0; i < taskSize; i++) {
executor.execute(new WorkTask(doneSingle));
}
executor.execute(new AllTaskDonedTask(countDownLatch));
}
static class WorkTask implements Runnable {
CountDownLatch mCountDownLatch;
public WorkTask(CountDownLatch countDownLatch) {
mCountDownLatch = countDownLatch;
}
@Override
public void run() {
try {
println(Thread.currentThread().getName()+" execute task....");
Thread.sleep(1000);//模拟耗时操作
mCountDownLatch.countDown();//任务执行完毕计数器减1
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//所有任务执行完毕后需要执行的任务
static class AllTaskDonedTask implements Runnable {
CountDownLatch mCountDownLatch;
public AllTaskDonedTask(CountDownLatch countDownLatch) {
mCountDownLatch = countDownLatch;
}
@Override
public void run() {
try {
mCountDownLatch.await();//此处会使当前线程处于等待状态,直到3个WorkTask全部执行完毕,才会继续执行下面
println("所有任务执行完毕我才执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
执行结果:
pool-1-thread-3 execute task....
pool-1-thread-1 execute task....
pool-1-thread-2 execute task....
所有任务执行完毕我才执行
从上面代码我们不难看出,我们在执行WorkTask任务结束时都需要对计数器减1;在AllTaskDonedTask任务执行前需要调用CountDownLatch.await()方法,这样当前线程会处于等待状态,直到计数器减为0时也即WorkTask任务都执行完毕后,AllTaskDonedTask方可执行。