本文代码基于Java8
前言
CountDownLatch
,英文翻译为倒计时锁存器,是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。也是基于 AQS,它是 AQS 的共享功能的一个实现。
它主要用来保证完成某个任务的先决条件满足,是一个同步工具类,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。
- 确保某个计算在其需要的所有资源都被初始化之后才继续执行;
- 确保某个服务在其依赖的所有其他服务都已经启动之后才启动;
- 等待直到某个操作所有参与者都准备就绪再继续执行。
CountDownLatch
有一个正数计数器,countDown()
方法对计数器做减操作,await()
方法等待计数器达到0。所有 await 的线程都会阻塞直到计数器为0或者等待线程中断或者超时。
CountDownLatch 类结构
其中Sync
是 CountDownLatch
的内部类,Sync
继承自 AbstractQueuedSynchronizer
。使用 AQS state 表示 count 计数。
1 | private static final class Sync extends AbstractQueuedSynchronizer { |
CountDownLatch 构造方法
使用给定的 count 构造 CountDownLatch
,count 表示线程通过 await 前必须要执行的次数,count 不能小于0。
1 | public CountDownLatch(int count) { |
CountDownLatch
是一次性的,计数器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch
使用完毕后,它不能再次被使用。
CountDownLatch 线程等待方法
await()
是通过轮询 state 的状态来判断所有的任务是否都完成。
无限等待
让当前线程等待直到 count 减数为0,除非线程被中断。如果 count 为0,线程将立即返回,不再阻塞等待。
如果当前计数大于零,则出于线程调度目的,当前线程将禁用,并处于休眠状态,直到发生以下两种情况之一:
countDown()
方法调用使得 count 减数为0;- 当前线程被中断 (如果被中断将会抛出 InterruptedException 异常)。
1 | public void await() throws InterruptedException { |
超时等待
使当前线程处理等待状态直到 count 减为0或者等待超时。如果当前count是0,则线程立即返回true。
如果当前计数大于零,则出于线程调度目的,当前线程将禁用,并处于休眠状态,直到发生以下三种情况之一:
countDown()
方法调用使得 count 减数为0;- 当前线程被中断 (如果被中断将会抛出 InterruptedException 异常);
- 等待超时。
如果等待超时但是 count>0
,则返回 false。如果超时时间小于或等于零,方法将不会等待。
1 | public boolean await(long timeout, TimeUnit unit) |
CountDownLatch 其他方法
1 | // 倒计时,将会将count-1 |
AQS 的 doReleaseShared() 方法
1 | private void doReleaseShared() { |
使用示例
官方示例
1 | class Driver { // ... |
火箭发射示例
1 | public class CountDownLatchDemo implements Runnable{ |
总结
CountDownLatch
主要用来保证完成某个任务的先决条件满足,是一个同步工具类,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。