概念
CountDownLatch是一个通用的同步工具,CountDownLatch允许一个或多个线程在其他线程执行操作完成前等待。
用法
CountDownLatch需要初始化一个计数器,调用await()方法使线程阻塞,调用countDown()方法让计数器减一,当计数器减为零时,所有等待的线程释放,并且后续await()的线程立即执行。
场景
使用CountDownLatch主要有两个场景
- 主线程阻塞直到子线程全部执行完毕。比如,我和女朋友一起去吃麻辣烫,厨师需要等我和女朋友全部点完配菜之后才可以开始制作,而我和女朋友选菜的过程是可以同时进行的。
1 | public class CDLForSpicyHotPot { |
- 子线程先阻塞直到主线程执行了具体步骤后再一起执行。比如我们常说的发令枪场景
1 | public class CDLForStartingGun { |
注意:此处需要注意的是线程池核心线程数和运动员数量的设置,如果CPU无法处理太多的线程,运动员就可能不会同时runing
原理
- 使用构造函数传入计数,CountDownLatch使用AQS的state代表计数count
1 | //CountDownLatch的构造函数 |
1 | //CountDownLatch的内部类,继承了AQS |
使用await()使线程阻塞 ,await()会调用AQS的acquireSharedInterruptibly(1)方法
1
2
3
4
5
6
7
8
9public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//Sync的实现,计数不为0则是true
if (tryAcquireShared(arg) < 0)
//AQS的方法,使用park阻塞线程
doAcquireSharedInterruptibly(arg);
}
- 使用countDown()使计数减一,直到减为零
1 | public final boolean releaseShared(int arg) { |
CountDownLatch包括很多其他的锁的都是基于AQS(AbstractQueuedSynchronizer)来实现的,后续我会持续更新相关的JAVA知识,希望能够帮助到大家。
欢迎关注我的公众号“shy先生”,很高兴能与大家一起成长。