Класс 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 =" и текущее значение.- Переопределяет:
-
toStringв классеObject - Возвращает:
- строка, идентифицирующая данный счётчик обратного отсчёта, а также его состояние
© 1993, 2021, 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/17/docs/api/java.base/java/util/concurrent/CountDownLatch.html