Класс CountDownLatch

public class CountDownLatch
extends Object

Средство синхронизации, позволяющее одному или нескольким потокам ожидать завершения набора операций, выполняемых в других потоках.

A CountDownLatch инициализируется заданным значением count. Методы await блокируют выполнение, пока текущее значение count не достигнет нуля в результате вызовов метода countDown(), после чего все ожидающие потоки освобождаются, и любые последующие вызовы await возвращают результат немедленно. Это одноразовое явление — значение count не может быть сброшено. Если вам нужна версия, позволяющая сбрасывать значение count, используйте CyclicBarrier.

A CountDownLatch — универсальный инструмент синхронизации, который можно использовать для различных целей. A CountDownLatch с начальным значением count, равным единице, служит простым триггером включения/выключения или шлюзом: все потоки, вызывающие await, ждут при входе в шлюз, пока он не будет открыт потоком, вызывающим countDown(). A CountDownLatch с начальным значением N может быть использована, чтобы заставить один поток ждать, пока N потоков не завершат определённое действие, или пока действие не будет выполнено N раз.

Полезное свойство CountDownLatch состоит в том, что потоки, вызывающие countDown , не требуют, чтобы значение count достигло нуля перед продолжением, оно просто предотвращает любой поток от прохождения после 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 в 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() {
     try {
       doWork(i);
       doneSignal.countDown();
     } catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }

Влияние согласованности памяти: до тех пор, пока значение count не достигнет нуля, действия в потоке до вызова countDown() предшествуют действиям, следующим за успешным возвратом из соответствующего await() в другом потоке.

Since:
1.5

Конструкторы

Конструктор Описание
CountDownLatch​(int count)

Инициализирует CountDownLatch заданным значением count.

Методы

Модификатор и тип Метод Описание
void await()

Заставляет текущий поток ждать, пока затвор не будет уменьшен до нуля, если поток не прерван.

boolean await​(long timeout, TimeUnit unit)

Заставляет текущий поток ждать, пока затвор не будет уменьшен до нуля, если поток не прерван, или не истечёт указанное время ожидания.

void countDown()

Уменьшает значение счетчика затвора, освобождая все ожидающие потоки, если значение счетчика достигает нуля.

long getCount()

Возвращает текущее значение count.

String toString()

Возвращает строку, идентифицирующую этот затвор и его состояние.

Методы, объявленные в классе java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

Подробное описание конструкторов

CountDownLatch

public CountDownLatch(int count)

Инициализирует CountDownLatch заданным значением count.

Parameters:
count - количество вызовов countDown(), необходимое для того, чтобы потоки смогли пройти через await()
Throws:
IllegalArgumentException - если count отрицательно

Подробное описание методов

await

public void await()
           throws InterruptedException

Заставляет текущий поток ждать, пока затвор не будет уменьшен до нуля, если поток не прерван.

Если текущее значение count равно нулю, этот метод возвращает результат немедленно.

Если текущее значение count больше нуля, текущий поток отключается для планирования потоков и находится в ожидании, пока не произойдёт одно из двух событий:

  • Значение count достигает нуля в результате вызовов метода countDown(); или
  • Другой поток прерывает текущий поток.

Если в текущем потоке:

  • Флаг прерывания установлен при входе в этот метод; или
  • Поток прерывается во время ожидания,
то выбрасывается исключение InterruptedException, и флаг прерывания текущего потока сбрасывается.
Throws:
InterruptedException - если текущий поток прерывается во время ожидания

await

public boolean await(long timeout,
                     TimeUnit unit)
              throws InterruptedException

Заставляет текущий поток ждать, пока затвор не будет уменьшен до нуля, если поток не прерван, или не истечёт указанное время ожидания.

Если текущее значение count равно нулю, этот метод возвращает результат немедленно со значением true.

Если текущее значение count больше нуля, текущий поток отключается для планирования потоков и находится в ожидании, пока не произойдёт одно из трёх событий:

  • Значение count достигает нуля в результате вызовов метода countDown(); или
  • Другой поток прерывает текущий поток; или
  • Истекает указанное время ожидания.

Если значение count достигает нуля, метод возвращает значение true.

Если в текущем потоке:

  • Флаг прерывания установлен при входе в этот метод; или
  • Поток прерывается во время ожидания,
то выбрасывается исключение InterruptedException, и флаг прерывания текущего потока сбрасывается.

Если указанное время ожидания истекает, возвращается значение false. Если время равно или меньше нуля, метод вообще не будет ожидать.

Parameters:
timeout - максимальное время ожидания
unit - единица измерения времени для аргумента timeout
Returns:
true если значение count достигло нуля, и false если время ожидания истекло до достижения нуля count
Throws:
InterruptedException - если текущий поток прерывается во время ожидания

countDown

public void countDown()

Уменьшает значение счетчика затвора, освобождая все ожидающие потоки, если значение счётчика достигает нуля.

Если текущее значение count больше нуля, оно уменьшается. Если новое значение count равно нулю, все ожидающие потоки снова активируются для планирования потоков.

Если текущее значение count равно нулю, ничего не происходит.

getCount

public long getCount()

Возвращает текущее значение count.

Этот метод обычно используется для отладки и тестирования.

Returns:
текущее значение count

toString

public String toString()

Возвращает строку, идентифицирующую этот затвор и его состояние. Состояние, в скобках, включает строку "Count =" и текущее значение count.

Overrides:
toString в классе Object
Returns:
строка, идентифицирующая этот затвор и его состояние

© 1993, 2020, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CountDownLatch.html

Spec-Zone .ru
спецификации, руководства, описания, API