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