CountDownLatch适⽤于在多线程的场景需要等待所有⼦线程全部执⾏完毕之后再做操作的场景。
举个例⼦,早上部⻔开会,有⼈在上厕所,这时候需要等待所有⼈从厕所回来之后才能开始会议。
public class CountDownLatchTest {
private static int num = 3;
private static CountDownLatch countDownLatch = new
CountDownLatch(num);
private static ExecutorService executorService =
Executors.newFixedThreadPool(num);
public static void main(String[] args) throws Exception{
executorService.submit(() -> {
System.out.println("A在上厕所");
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();
System.out.println("A上完了");
}
});
executorService.submit(()->{
System.out.println("B在上厕所");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();
System.out.println("B上完了");
}
});
executorService.submit(()->{
System.out.println("C在上厕所");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();
System.out.println("C上完了");
}
});
System.out.println("等待所有⼈从厕所回来开会...");
countDownLatch.await();
System.out.println("所有⼈都好了,开始开会...");
executorService.shutdown();
}
}
代码执⾏结果:
初始化⼀个CountDownLatch实例传参3,因为我们有3个⼦线程,每次⼦线程执⾏完毕之后调⽤countDown()⽅法给计数器-1,主线程调⽤await()⽅法后会被阻塞,直到最后计数器变为0,await()⽅法返回,执⾏完毕。他和join()⽅法的区别就是join会阻塞⼦线程直到运⾏结束,⽽CountDownLatch可以在任何时候让await()返回,⽽且⽤ExecutorService没法⽤join了,相⽐起来,CountDownLatch更灵活。
CountDownLatch基于AQS实现,volatile变量state维持倒数状态,多线程共享变量可⻅。
1. CountDownLatch通过构造函数初始化传⼊参数实际为AQS的state变量赋值,维持计数器倒数状态
2. 当主线程调⽤await()⽅法时,当前线程会被阻塞,当state不为0时进⼊AQS阻塞队列等待。
3. 其他线程调⽤countDown()时,state值原⼦性递减,当state值为0的时候,唤醒所有调⽤await()⽅
法阻塞的线程
网友评论