概述
- 允许一个线程的或多个线程等待其他线程完成操作。和join方法类似,初始化对象时通过传入一个固定的计数器总数,线程方法执行时调用countDown给计数器减1,当计数器0时,就会恢复等待的线程继续执行。
- CountDownLatch的计数器不能重用。只能使用一次
*常用的使用场景是提升程序的并行效率,同时处理多个任务后,最后需要提示任务完成。类似的表格的批量解析读取。
使用方法
一个线程等待
1 | static CountDownLatch c=new CountDownLatch(2); |
输出结果
1 | 初始化任务数:2 |
多个线程等待
1 | static CountDownLatch countDownLatch=new CountDownLatch(3); |
输出结果
1 | Thread-1:开始处理表格数据 |
源码分析
获取一个countDownLatch时
- 源码中可以看出是如果初始传入的j计数器为0时是直接抛出异常的;
- 内部是通过new Sync一个内部返回一个对象的。Sync是一个内部同步器类,继承AQS。
Sync内部类
1 | private static final class Sync extends AbstractQueuedSynchronizer { |
await方法
1 | public void await() throws InterruptedException { |
- await方法是通过sync内部类调用AQS中的
acquireSharedInterruptibly()
方法 - 执行
await
方法的线程会在计数器没有成为0时一直处于等待,除非线程被中断,支持可中断的。
1 | public final void acquireSharedInterruptibly(int arg) |
countDown执行计数器减法操作
countDownf方法每执行一次,计数器就减1,如果计数到达零,则释放所有等待的线程
1 | public void countDown() { |
doReleaseShared方法会依自旋的方式不断尝试释放同步状态
1 | private void doReleaseShared() { |
总结
- CountDownLatch是基于AQS实现的一个并发工具类,允许一个线程或多个线程等待其它线程操作,初始化是传入总的计数器,内部都通过
new Sync
一个返回一个对象。当调用countDown()方法 就会吧计数器做递减,当计数器为0时,就会恢复等待的线程继续执行,计数到达零之前,await 方法会一直受阻塞。
java知识归纳总结
github: https://a870439570.github.io/interview-docs