举例:火箭发射倒计时
一、定义
countDownLatch从字面上理解,countDown倒计时的意思latch是锁、门栓的意思,那么countDownLatch就是倒计时的门栓 。
JDK1.5中提供了JAVA.util.concurrent.CountDownLatch类,用于一个或多个类等待一直到其他线程完成一系列操作 。
CountDownLatch创建时设置一个count值,表示倒计时的次数,然后等待状态的线程调用CountDownLatch的await()方法进行等待,倒计时的方法是countDown(), 每次countDown都会减少count的值,直到count为0,则所有的await()的线程都会从等待中返回 。
二、使用
我们使用员工下班值班人员锁门案例进行演示
for (int i=1;i<=6;i++){
new Thread(() -> {
System.out.println("第"+Thread.currentThread().getName()+"t 位员工离开房间");
},String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName()+"t 值班人员最后关门走人");
如果我们不使用CountDownLatch 这样就会导致员工还没有全部离开房间,这个时候管理员把门锁上 。
运行结果
文章插图
没有使用CountDownLatch 运行结果
使用CountDownLatch代码如下
CountDownLatch countDownLatch = new CountDownLatch(6);for (int i=1;i<=6;i++){new Thread(() -> {System.out.println("第"+Thread.currentThread().getName()+"t 位员工离开房间");countDownLatch.countDown();},String.valueOf(i)).start();}countDownLatch.await();System.out.println(Thread.currentThread().getName()+"t 值班人员最后关门走人");
运行结果:文章插图
使用CountDownLatch运行结果
三、原理
在上面我们看到,CountDownLatch主要使用CountDown方法进行减1的操作,使用await方法进行等到操作 。
1、CountDown原理
文章插图
CountDownLatch里面保存了一个count值,通过减1操作,直到为0时候,等待线程才可以执行 。而且通过源码也可以看到这个countDown方法其实是通过sync调用releaseShared(1)来完成的 。
sync是个什么,releaseShared方法又是如何实现的 。我们不妨接着看源码,在CountDownLatch的开头我们找到了答案,原来这个sync在这里定义了 。
文章插图
在这里我们发现继承了AbstractQueuedSynchronizer(AQS) 。AQS的其中一个作用就是维护线程状态和获取释放锁 。在这里也就是说CountDownLatch使用AQS机制维护锁状态 。而releaseShared(1)方法就是释放了一个共享锁 。
现在理解了吧,底层使用AQS机制调用releaseShared方法释放一个锁资源 。
那么等待的方法是如何实现的呢?
2、await原理
文章插图
文章插图
这两个方法都是让线程等待,一个有时间限制、一个没有时间限制
await()方法底层主要是显示acquireSharedInterruptibly()方法来实现的
文章插图
首先acquireSharedInterruptibly方法里面有两个if语句,第一个判断是否被中断,如果被中断了,那就抛出中断异常,然后判断是否还有线程未执行,如果有那就执行 。
tryAcquireShared方法就是判断countDown是否减到了0,如果到了0,那就返回1,不需要等待,如果没有到0 说明还有未执行的线程,继续等待所有线程执行结束
doAcquireSharedInterruptibly方法是如何实现的
文章插图
大致意思我可以描述一下,他会用一个一个的节点将线程串起来 等达到条件后再一个一个的唤醒 。核心就是第三行的addWaiter函数 。我们可以再跟进去看看吧 。
文章插图
这里面使用cas机制 。
对于CountDownLatch来说原理主要还是通过源码来认识 。不过CountDownLatch看起来虽然很好用,也有很多不足之处,比如说CountDownLatch是一次性的 , 计数器的值只能在构造方法中初始化一次 , 之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后 , 它不能再次被使用 。
【多线程中countDownLatch的使用】
推荐阅读
- 驼鹿体型有多大 世界上最矮的长颈鹿是多少米?
- 月亮与银河的位置关系是什么 月亮是银河系中的一颗什么星
- 在华为鲲鹏服务器的OpenEuler操作系统中快速部署OpenGauss数据库
- 简单三步完成Excel多文件汇总
- 这种复杂的多条件关键词归类查询技术,只有5.6%的Excel高手会用
- JAVA多线程-Exchanger
- MyBatis插件-慢sql耗时监控插件
- 霍山和黄芽属于哪种茶,霍山黄芽价格多少
- 教你如何解决Win10驱动升级Bug
- 如何使用Istio 1.6管理多集群中的微服务?