
文章插图
在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、BlockingDeque接口、ConcurrentHashMap , 本文为系列文章第九篇 。
【java并发编程实战 pdf java并发编程JUC第九篇:CountDownLatch线程同步】CountDownLatch是一种线程同步辅助工具 , 它允许一个或多个线程等待其他线程正在执行的一组操作完成 。CountDownLatch的概念在java并发编程中非常常见 , 面试也会经常被问到 , 所以一定要好好理解掌握 。在这篇文章中 , 我将介绍以下几点
- CountDownLatch是什么?
- CountDownLatch 如何工作
- CountDownLatch 代码例子
CountDownLatch用线程数来初始化一个计数器 , 每当一个线程完成执行时 , 这个计数器就会递减 。当计数为零时 , 表示所有线程都已完成执行 , 处于等待状态的主线程可以继续执行 。

文章插图
下面我们使用伪代码的方式描述CountDownLatch 的作用
- 主线程启动 , 并为N个线程(假设n=3)初始化CountDownLatch(n)
- 启动n个线程
- 主线程阻塞等待
- 线程1执行完成 , CountDownLatch -1 = 2 , 主线程继续阻塞
- 线程3执行完成 , CountDownLatch -1 = 1 , 主线程继续阻塞
- 线程4执行完成 , CountDownLatch -1 = 0 , 主线程恢复执行
CountDownLatch.public CountDownLatch(int count) {...}使用CountDownLatch的主线程要去等待其他线程执行完成 , 所以这个主线程必须在启动其他线程后立即调用 CountDownLatch.await() 方法 , 该方法阻塞主线程处于等待状态 , 直到其他线程执行完毕 , 才会停止阻塞 。其他N个线程必须有CountDownLatch对象的引用 , 因为它们需要通知CountDownLatch对象它们已经完成任务 。这个通知是由方法
CountDownLatch.countDown()来完成的 , 每调用一次该方法 , 就会将构造函数中设置的初始计数count减少1 , 所以当所有N个线程都调用了这个方法后count计数达到0 , 主线程就可以不受await()方法阻塞恢复执行了 。所以CountDownLatch特别适合于那些需要等待N个线程完成后再开始执行的场景 。例如一个应用程序的启动类 , 在处理用户请求之前 , 要确保所有N个外部系统都是处于运行状态的 。
CountDownLatch 代码例子假设我们的应用程序主线程启动之前 , 要检查另外4个程序是否准备就绪 , 只有其他的4个程序准备就绪 , 我们的主程序才能继续执行 。就可以使用下面的代码来操作:
import java.util.concurrent.CountDownLatch;public class Tester { public static void main(String args[]) { //设置计数器 counter = 4 , 等于线程数 CountDownLatch countDownLatch = new CountDownLatch(4); Thread app1 = new Thread(new Application("App1", countDownLatch)); Thread app2 = new Thread(new Application("App2", countDownLatch)); Thread app3 = new Thread(new Application("App3", countDownLatch)); Thread app4 = new Thread(new Application("App4", countDownLatch)); // 启动多线程去检查其他四个程序的可用状态 app1.start(); app2.start(); app3.start(); app4.start(); try { //主线程调用await进行等待 , 等待上述四个线程正常完成 countDownLatch.await(); //上述四个线程检查的应用程序启动正常之后, 打印如下信息 System.out.println("All applications are up and running."); } catch(InterruptedException e) { System.out.println(e.getMessage()); } }}子线程程序 , 每一个线程都持有countDownLatch对象 , 线程正常执行完成之时 , 使用countDownLatch.countDown()方法将countDownLatch对象的计数器减1 。class Application implements Runnable { private String name; //应用程序名称 private CountDownLatch countDownLatch; public Application(String name, CountDownLatch countDownLatch) { this.name = name; this.countDownLatch = countDownLatch; } public void run() { try { System.out.println(name + " started. "); Thread.sleep(1000); } catch (InterruptedException e) { System.out.println(e.getMessage()); } System.out.println( name + " is Up and running."); //将countDownLatch计数器的值减1 countDownLatch.countDown(); }}上述程序的打印输出结果是 , 可以结合输出结果去理解上文中讲述的CountDownLatch 工作原理:App2 started. App3 started. App1 started. App4 started. App1 is Up and running.App3 is Up and running.App4 is Up and running.App2 is Up and running.All applications are up and running.欢迎关注我的博客 , 里面有很多精品合集- 本文转载注明出处(必须带连接 , 不能只转文字):字母哥博客 。
- 《手摸手教你学Spring Boot2.0》
- 《Spring Security-JWT-OAuth2一本通》
- 《实战前后端分离RBAC权限管理系统》
- 《实战SpringCloud微服务从青铜到王者》
- 《VUE深入浅出系列》
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
