模块 java.base

类 CountDownLatch

java.lang.Object
java.util.concurrent.CountDownLatch

public class CountDownLatch extends Object
一种同步辅助工具,允许一个或多个线程等待,直到其他线程中执行的一组操作完成。

CountDownLatch 使用给定的 count 进行初始化。 await 方法会阻塞,直到当前计数由于调用 countDown() 方法而变为零,之后所有等待的线程都会被释放,并且任何后续的 await 调用都会立即返回。这是一种一次性现象——无法重置计数。如果您需要重置计数的版本,请考虑使用 CyclicBarrier

CountDownLatch 是一种多功能同步工具,可用于多种用途。初始化为 1 的 CountDownLatch 用作简单的开/关锁存器或门:所有调用 await 的线程都在门处等待,直到它被调用 countDown() 的线程打开。初始化为 NCountDownLatch 可用于使一个线程等待,直到 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 来描述每个部分,该 Runnable 执行该部分并在闩锁上倒计时,并将所有 Runnable 排队到一个 Executor。当所有的子部分都完成后,协调线程就可以通过await了。 (当线程必须以这种方式重复倒计时时,请改用 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() {
   doWork();
   doneSignal.countDown();
  }

  void doWork() { ... }
 } 

内存一致性影响:在计数达到零之前,调用 countDown() 发生在之前 之前线程中的操作从另一个线程中相应的 await() 成功返回。

自从:
1.5
  • 构造方法总结

    构造方法
    构造方法
    描述
    CountDownLatch(int count)
    构造一个用给定计数初始化的 CountDownLatch
  • 方法总结

    修饰符和类型
    方法
    描述
    void
    导致当前线程等待,直到锁存器倒计时到零,除非线程是 interrupted
    boolean
    await(long timeout, TimeUnit unit)
    导致当前线程等待,直到锁存器倒计时为零,除非线程为 interrupted 或指定的等待时间已过。
    void
    减少闩锁的计数,如果计数达到零,则释放所有等待的线程。
    long
    返回当前计数。
    返回标识此锁存器及其状态的字符串。

    在类 java.lang.Object 中声明的方法

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
  • 构造方法详细信息

    • CountDownLatch

      public CountDownLatch(int count)
      构造一个用给定计数初始化的 CountDownLatch
      参数:
      count - 在线程可以通过 await() 之前必须调用 countDown() 的次数
      抛出:
      IllegalArgumentException - 如果 count 为负
  • 方法详情

    • await

      public void await() throws InterruptedException
      导致当前线程等待,直到锁存器倒计时到零,除非线程是 interrupted

      如果当前计数为零,则此方法立即返回。

      如果当前计数大于零,则当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下两种情况之一:

      • 由于调用了 countDown() 方法,计数达到零;或者
      • 一些其他线程 中断 当前线程。

      如果当前线程:

      • 在进入此方法时设置其中断状态;或者
      • 等待时是interrupted
      然后抛出InterruptedException 并清除当前线程的中断状态。
      抛出:
      InterruptedException - 如果当前线程在等待时被中断
    • await

      public boolean await(long timeout, TimeUnit  unit) throws InterruptedException
      导致当前线程等待,直到锁存器倒计时为零,除非线程为 interrupted 或指定的等待时间已过。

      如果当前计数为零,则此方法立即返回值 true

      如果当前计数大于零,则当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下三种情况之一:

      • 由于调用了 countDown() 方法,计数达到零;或者
      • 一些其他线程中断当前线程;或者
      • 指定的等待时间已过。

      如果计数达到零,则该方法返回值 true

      如果当前线程:

      • 在进入此方法时设置其中断状态;或者
      • 等待时是interrupted
      然后抛出InterruptedException 并清除当前线程的中断状态。

      如果指定的等待时间过去,则返回值 false。如果时间小于或等于零,则该方法根本不会等待。

      参数:
      timeout - 最长时间等待
      unit - timeout 参数的时间单位
      返回:
      true 如果计数达到零,false 如果在计数达到零之前等待时间过去
      抛出:
      InterruptedException - 如果当前线程在等待时被中断
    • countDown

      public void countDown()
      减少闩锁的计数,如果计数达到零,则释放所有等待的线程。

      如果当前计数大于零,则递减。如果新计数为零,则重新启用所有等待线程以用于线程调度目的。

      如果当前计数为零,则什么也不会发生。

    • getCount

      public long getCount()
      返回当前计数。

      此方法通常用于调试和测试目的。

      返回:
      当前计数
    • toString

      public String  toString()
      返回标识此锁存器及其状态的字符串。括号中的状态包括字符串 "Count =",后跟当前计数。
      重写:
      toString 在类 Object
      返回:
      标识此锁存器及其状态的字符串