Класс CountDownLatch
public class CountDownLatch extends Object
Объект CountDownLatch инициализируется заданным счётчиком. Методы await блокируются, пока текущее значение счётчика не достигнет нуля в результате вызовов метода countDown(), после чего все ожидающие потоки освобождаются, а все последующие вызовы await немедленно возвращают управление. Это одноразовый механизм — сбросить счётчик нельзя. Если вам нужна версия со сбросом счётчика, используйте CyclicBarrier.
Объект CountDownLatch — универсальное средство синхронизации, которое можно использовать для разных целей. Объект CountDownLatch, инициализированный значением счётчика, равным единице, служит простой защёлкой включения/выключения, или воротами: все потоки, вызывающие await, ожидают у ворот, пока поток, вызывающий countDown(), не откроет их. Объект CountDownLatch, инициализированный значением N, можно использовать, чтобы заставить один поток ожидать, пока 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 в очередь 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 |
Создаёт объект CountDownLatch с заданным значением счётчика. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
void |
await() |
Заставляет текущий поток ожидать, пока значение счётчика защёлки не достигнет нуля, если только поток не будет прерван. |
boolean |
await |
Заставляет текущий поток ожидать, пока значение счётчика защёлки не достигнет нуля, если только поток не будет прерван или не истечёт заданное время ожидания. |
void |
countDown() |
Уменьшает значение счётчика защёлки и освобождает все ожидающие потоки, если счётчик достигает нуля. |
long |
getCount() |
Возвращает текущее значение счётчика. |
String |
toString() |
Возвращает строку, идентифицирующую эту защёлку и описывающую её состояние. |
Подробное описание конструкторов
CountDownLatch
public CountDownLatch(int count)
CountDownLatch с заданным значением счётчика.- Параметры:
-
count— количество вызововcountDown(), необходимых для того, чтобы потоки могли пройти черезawait() - Исключения:
-
IllegalArgumentException— если значениеcountотрицательно
Подробное описание методов
await
public void await() throws InterruptedException
Если текущее значение счётчика равно нулю, этот метод немедленно возвращает управление.
Если текущее значение счётчика больше нуля, текущий поток отключается от планирования потоков и остаётся в ожидании до наступления одного из двух событий:
- Счётчик достигает нуля в результате вызовов метода
countDown(); или - Другой поток прерывает текущий поток.
Если текущий поток:
- входит в этот метод с установленным статусом прерывания; или
- был прерван во время ожидания,
InterruptedException, а статус прерывания текущего потока сбрасывается.- Исключения:
-
InterruptedException— если текущий поток прерван во время ожидания
await
public boolean await(long timeout, TimeUnit unit) throws InterruptedException
Если текущее значение счётчика равно нулю, этот метод немедленно возвращает значение true.
Если текущее значение счётчика больше нуля, текущий поток отключается от планирования потоков и остаётся в ожидании до наступления одного из трёх событий:
- Счётчик достигает нуля в результате вызовов метода
countDown(); или - Другой поток прерывает текущий поток; или
- Истекает заданное время ожидания.
Если счётчик достигает нуля, метод возвращает значение true.
Если текущий поток:
- входит в этот метод с установленным статусом прерывания; или
- был прерван во время ожидания,
InterruptedException, а статус прерывания текущего потока сбрасывается. Если заданное время ожидания истекает, возвращается значение false. Если время меньше или равно нулю, метод не будет ожидать.
- Параметры:
-
timeout— максимальное время ожидания -
unit— единица измерения времени аргументаtimeout - Возвращает:
-
true, если счётчик достиг нуля, иfalse, если время ожидания истекло до достижения счётчиком нуля - Исключения:
-
InterruptedException— если текущий поток прерван во время ожидания
countDown
public void countDown()
Если текущее значение счётчика больше нуля, оно уменьшается. Если новое значение равно нулю, все ожидающие потоки снова допускаются к планированию.
Если текущее значение счётчика равно нулю, ничего не происходит.
getCount
public long getCount()
Этот метод обычно используется для отладки и тестирования.
- Возвращает:
- текущее значение счётчика
toString
public String toString()
"Count =", за которым следует текущее значение счётчика.
© 1993, 2025, 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/25/docs/api/java.base/java/util/concurrent/CountDownLatch.html