CountDownLatch是一个同步的辅助类,主要作用是允许线程等待,直到等待的线程全部执行完成后才会继续往下走剩下的逻辑。
使用场景解析
首先,假设我的职业是一名厨师,我每天的任务是炒菜,今天有一个客人来点菜(主线程),那么我需要去买菜,洗菜等等,可是我又不想去,所以我找了几个小弟分别去买菜洗菜切菜(线程池,指挥他们去干活),可是我不知道他们什么时候能干好,我才能开始炒菜,所以我就给了他们我的手机号,(new一个CountDownLatch,就是我的手机),他们干完了就通知我(CountDownLatch.countDown()方法),然后我就开始睡觉(latch.await()方法,开始等待),直到我手机一共接到了三次电话我才会起身干活。
源码解析
我们一个一个来解析:
// 构造方法,传参一个Int类型的数字,也就是我们场景中提到的几个小弟
public CountDownLatch(int count){}
// 就是把CountDownLatch初始化的Int count数减1,可以理解成小弟给我打电话,通知我
public void countDown() {}
// 执行此方法的话,主线程就会一直等待,等待count数为0才会执行主线程,可以理解成线程在这里就阻塞了
public void await() throws InterruptedException {}
// 重载方法,跟上面的区别就是不会一直等待,会给一个参数,最长等待多久就继续执行,而不是一直堵死
public boolean await(long timeout, TimeUnit unit)throws InterruptedException {}
// 获取当前还剩多少个count数
public long getCount() {}
代码示范
System.out.println("客人来了");
// 线程池安排小弟去干活
ExecutorService threadPool = Executors.newFixedThreadPool(3);
// 给小弟我的手机号
CountDownLatch cdl = new CountDownLatch(5);
// 安排5个小弟
for(int i = 0; i<5;i++){
threadPool.submit(() -> {
try {
// 每个小弟干活的时间不一样
Thread.sleep((long)(Math.random()*10));
// 小弟干完给我打电话
cdl.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 我准备睡觉了,直到小弟全部干完我才开始干活
cdl.await();
//这里不关闭线程池的话,整个主线程虽然不执行东西了,但是还是会一直运行,不会停止
threadPool.shutdown();
}