- java.lang.Object
-
- java.util.concurrent.CountDownLatch
-
public class CountDownLatch extends Object
允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。使用给定计数初始化
CountDownLatch
。 所述await
种方法阻塞,直到当前计数达到零由于的调用countDown()
方法,之后所有等待的线程被释放和任何后续调用await
立即返回。 这是一次性现象 - 计数无法重置。 如果您需要重置计数的版本,请考虑使用CyclicBarrier
。CountDownLatch
是一种多功能同步工具,可用于多种用途。 初始化为计数为1的CountDownLatch
用作简单的开/关锁存器或门:所有调用await
的线程在门处等待,直到由调用countDown()
的线程打开它。 初始化为N的CountDownLatch
可用于使一个线程等待,直到N个线程完成某个动作,或者某个动作已完成N次。CountDownLatch
一个有用属性是它不需要调用countDown
线程等待计数在继续之前达到零,它只是阻止任何线程继续通过await
直到所有线程都可以通过。示例用法:这是一对类,其中一组工作线程使用两个倒计时锁存器:
- 第一个是启动信号,阻止任何工人继续工作,直到驱动程序准备好继续进行;
- 第二个是完成信号,允许驾驶员等到所有工人完成。
class Driver { // ... void main() throws InterruptedException { CountDownLatch startSignal = new CountDownLatch(1); CountDownLatch doneSignal = new CountDownLatch(N); for (int i = 0; i < N; ++i) // create and start threads new Thread(new Worker(startSignal, doneSignal)).start(); doSomethingElse(); // don't let run yet startSignal.countDown(); // let all threads proceed doSomethingElse(); doneSignal.await(); // wait for all to finish } } class Worker implements Runnable { private final CountDownLatch startSignal; private final CountDownLatch doneSignal; Worker(CountDownLatch startSignal, CountDownLatch doneSignal) { this.startSignal = startSignal; this.doneSignal = doneSignal; } public void run() { try { startSignal.await(); doWork(); doneSignal.countDown(); } catch (InterruptedException ex) {} // return; } void doWork() { ... } }
另一个典型的用法是将问题分成N个部分,用执行该部分的Runnable描述每个部分并对锁存器进行倒计时,并将所有Runnables排队到Executor。 当所有子部件都完成后,协调线程将能够通过等待。 (当线程必须以这种方式重复倒计时时,请使用
CyclicBarrier
。 )class Driver2 { // ... void main() throws InterruptedException { CountDownLatch doneSignal = new CountDownLatch(N); Executor e = ... for (int i = 0; i < N; ++i) // create and start threads e.execute(new WorkerRunnable(doneSignal, i)); doneSignal.await(); // wait for all to finish } } class WorkerRunnable implements Runnable { private final CountDownLatch doneSignal; private final int i; WorkerRunnable(CountDownLatch doneSignal, int i) { this.doneSignal = doneSignal; this.i = i; } public void run() { try { doWork(i); doneSignal.countDown(); } catch (InterruptedException ex) {} // return; } void doWork() { ... } }
内存一致性影响:在计数达到零之前,在另一个线程中从相应的
await()
成功返回之后,在调用countDown()
happen-before之前的操作中的操作。- 从以下版本开始:
- 1.5
-
-
构造方法摘要
构造方法 构造器 描述 CountDownLatch(int count)
构造一个用给定计数初始化的CountDownLatch
。
-
-
-
构造方法详细信息
-
CountDownLatch
public CountDownLatch(int count)
构造一个用给定计数初始化的CountDownLatch
。- 参数
-
count
-的次数countDown()
前线程可以通过必须调用await()
- 异常
-
IllegalArgumentException
- 如果count
为负数
-
-
方法详细信息
-
await
public void await() throws InterruptedException
导致当前线程等到锁存器倒计数到零,除非该线程是interrupted 。如果当前计数为零,则此方法立即返回。
如果当前计数大于零,则当前线程将被禁用以进行线程调度,并且在发生以下两种情况之一之前处于休眠状态:
- 由于调用了
countDown()
方法,计数达到零; 要么 - 一些其他线程interrupts当前线程。
如果当前线程:
- 在进入此方法时设置其中断状态; 要么
- 等待时是interrupted ,
InterruptedException
并清除当前线程的中断状态。- 异常
-
InterruptedException
- 如果当前线程在等待时被中断
- 由于调用了
-
await
public boolean await(long timeout, TimeUnit unit) throws InterruptedException
导致当前线程等待,直到锁存器倒计数到零,除非线程是interrupted ,或者指定的等待时间过去。如果当前计数为零,则此方法立即返回值
true
。如果当前计数大于零,则当前线程因线程调度而被禁用,并且在发生以下三种情况之一之前处于休眠状态:
- 由于调用了
countDown()
方法,计数达到零; 要么 - 其他一些线程interrupts当前线程; 要么
- 指定的等待时间过去了。
如果计数达到零,则方法返回值
true
。如果当前线程:
- 在进入此方法时设置其中断状态; 要么
- 等待时是interrupted
InterruptedException
并清除当前线程的中断状态。如果指定的等待时间过去,则返回值
false
。 如果时间小于或等于零,则该方法将不会等待。- 参数
-
timeout
- 等待的最长时间 -
unit
-timeout
参数的时间单位 - 结果
-
true
如果计数达到零和false
如果计数达到零之前的等待时间流逝 - 异常
-
InterruptedException
- 如果当前线程在等待时被中断
- 由于调用了
-
countDown
public void countDown()
减少锁存器的计数,如果计数达到零则释放所有等待的线程。如果当前计数大于零,则递减。 如果新计数为零,则重新启用所有等待线程以进行线程调度。
如果当前计数等于零,则没有任何反应。
-
getCount
public long getCount()
返回当前计数。此方法通常用于调试和测试目的。
- 结果
- 目前的数量
-
-