CountDownLatch 作用
CountDownLatch 是 java.util.concurrent 包中的一个类,它主要用来协调多个线程之间的同步,起到一个同步器的作用。总的来说,CountDownLatch 让一个或多个线程在运行过程中的某个时间点能停下来等待其他的一些线程完成某些任务后再继续运行。
类似的任务可以使用线程的 join () 方法实现:在等待时间点调用其他线程的 join () 方法,当前线程就会等待 join 线程执行完之后才继续执行,但 CountDownLatch 实现更加简单,并且比 join 的功能更多。
CountDownLatch 使用
CountDownLatch 的构造函数接收一个 int 型参数作为计数器,例如想让 N 任务完成之后才能继续执行,创建 CountDownLatch 时传入参数 N;
需要等待的线程会调用 CountDownLatch 的 await 方法,该线程就会阻塞直到计数器的值减为 0,而达到自己预期的线程会调用 CountDownLatch 的 countDown () 方法,计数器 N 的值减 1。由于 countDown 方法可以在任何地方调用,所以计数器 N 既可以代表 N 个线程,也可以是一个线程的 N 个执行步骤。代表多个线程时,只需要将这个 CountDownLatch 的引用传到线程里面即可。
N 的值为 1 时,退化为单一事件,即由一个线程来通知其他线程,效果等同于对象的 wait 和 notifyAll;N 为 0 时,调用 await 方法不会阻塞当前线程。
步骤
- 首先创建 CountDownLatch 实例,通过构造函数指定计数器的值 N;
- 需要等待的线程调用 CountDownLatch 实例的 await 方法,等待计数器的值降为 0;
- 被等待的线程在任务完成时调用 CountDownLatch 实例的 countDown 方法,计数器的值减一。
示例
1 | public class CountDownLatchTest { |
CountDown 源码分析
分析 CountDownLatch 的源码可以知道,它使用了一个内部同步器 AQS 来实现屏蔽功能。只有当 count 的值为零时,同步器的 tryAcquireShared 结果才为 1,其他时候都是 -1。详细代码如下:
1 | private static final class Sync extends AbstractQueuedSynchronizer { |
CountDownLatch 不足
CountDownLatch 是一次性的,不可重新初始化 或 修改其内部计数器的值,当 CountDownLatch 使用完毕后,它不能再次被使用。