CountDownLatch
它是用来控制一个或者多个线程等待多个线程。
它的实现原理是内部使用了一个ctn的计数器,当调用countDown()方法的时候计数器就执行减1操作直到减到0的的时候那些之前调用await()方法而在等待的线程就会被唤醒。
有一个场景可以很好理解这个关键字的使用:火箭发射案例。火箭发射的时候需要每个子程序都准备好才能发射,如何做到让各个子程序异步的去执行自己的程序然后都准备完成再发射火箭呢?
demo如下
package com.leo.demo.threadtest.countdownlatch;
import java.util.concurrent.*;
/**
* @ClassName: RocketLatchingTest
* @Description: 火箭发射的案例
* 1、管理发射的主程序需要等待各个检查子程序完成才能发射
* @Author: leo825
* @Date: 2019-08-21 10:10
* @Version: 1.0
*/
public class RocketLatchingTest {
public static void main(String[] args) throws InterruptedException {
//子线程阻塞
CountDownLatch childPro = new CountDownLatch(5);
//生成随机数模拟子程序执行消耗时间
ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
//模拟火箭发射子程序的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
//模拟一个随机代表每一个子程序的耗时
int costTime = threadLocalRandom.nextInt(10);
executor.submit(() -> {
try {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " 开始处理子程序...");
System.out.println(threadName + " 处理时间为:" + costTime + "s");
TimeUnit.SECONDS.sleep(costTime);
System.out.println(Thread.currentThread().getName() + " 准备就绪!!!");
childPro.countDown();//完成预期工作并发出完成信号
} catch (Exception e) {
e.printStackTrace();
}
});
}
System.out.println("发射程序开始准备...");
childPro.await();
//模拟火箭发射倒计时
for (int i = 10; i > 0; i--) {
System.out.println("发射倒计时:" + i);
TimeUnit.SECONDS.sleep(1);
}
System.out.println("点火!!!");
executor.shutdown();
}
}
运行结果如下:
发射程序开始准备...
pool-1-thread-1 开始处理子程序...
pool-1-thread-1 处理时间为:8s
pool-1-thread-2 开始处理子程序...
pool-1-thread-2 处理时间为:9s
pool-1-thread-5 开始处理子程序...
pool-1-thread-4 开始处理子程序...
pool-1-thread-3 开始处理子程序...
pool-1-thread-4 处理时间为:8s
pool-1-thread-5 处理时间为:2s
pool-1-thread-3 处理时间为:7s
pool-1-thread-5 准备就绪!!!
pool-1-thread-3 准备就绪!!!
pool-1-thread-1 准备就绪!!!
pool-1-thread-4 准备就绪!!!
pool-1-thread-2 准备就绪!!!
发射倒计时:10
发射倒计时:9
发射倒计时:8
发射倒计时:7
发射倒计时:6
发射倒计时:5
发射倒计时:4
发射倒计时:3
发射倒计时:2
发射倒计时:1
点火!!!