Класс CountDownLatch
Класс CountDownLatch - это синхронизатор из пакета
java.util.concurrent, который позволяет одному или
нескольким потокам ожидать, пока набор операций,
выполняемых в других потоках, не завершится. В конструктор
класса мы передаем счетчик - целое число, которое
уменьшается методом countDown при завершении каждой
операции. Поток, вызвавший метод await, блокируется
до тех пор, пока счетчик не достигнет нуля.
Класс CountDownLatch является одноразовым: после
того как счетчик достиг нуля, его нельзя сбросить.
Если нужен переиспользуемый барьер, следует использовать
CyclicBarrier.
Синтаксис
CountDownLatch latch = new CountDownLatch(count);
latch.countDown();
latch.await();
latch.await(timeout, unit);
long count = latch.getCount();
Пример
Давайте создадим CountDownLatch со счетчиком
3 и запустим три рабочих потока, каждый из которых
уменьшает счетчик. Главный поток дожидается завершения
всех операций:
import java.util.concurrent.CountDownLatch;
public class Main
{
public static void main(String[] args) throws InterruptedException
{
CountDownLatch latch = new CountDownLatch(3);
for (int i = 1; i <= 3; i++)
{
final int id = i;
new Thread(() -> {
System.out.println("Thread " + id + " started");
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
System.out.println("Thread " + id + " finished");
latch.countDown();
}).start();
}
latch.await();
System.out.println("All threads finished");
}
}
Результат выполнения кода:
Thread 1 started
Thread 2 started
Thread 3 started
Thread 1 finished
Thread 2 finished
Thread 3 finished
All threads finished
Пример
Давайте используем метод getCount, чтобы посмотреть
текущее значение счетчика до и после вызовов
countDown:
import java.util.concurrent.CountDownLatch;
public class Main
{
public static void main(String[] args) throws InterruptedException
{
CountDownLatch latch = new CountDownLatch(3);
System.out.println("Initial count: " + latch.getCount());
latch.countDown();
System.out.println("After first countDown: " + latch.getCount());
latch.countDown();
System.out.println("After second countDown: " + latch.getCount());
latch.countDown();
System.out.println("After third countDown: " + latch.getCount());
latch.await();
System.out.println("Latch released");
}
}
Результат выполнения кода:
Initial count: 3
After first countDown: 2
After second countDown: 1
After third countDown: 0
Latch released
Пример
Давайте используем версию метода await с таймаутом,
чтобы главный поток не ждал бесконечно, если рабочие
потоки не успевают:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Main
{
public static void main(String[] args) throws InterruptedException
{
CountDownLatch latch = new CountDownLatch(5);
new Thread(() -> {
try
{
Thread.sleep(200);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
latch.countDown();
latch.countDown();
}).start();
boolean released = latch.await(100, TimeUnit.MILLISECONDS);
System.out.println("Released: " + released);
System.out.println("Remaining count: " + latch.getCount());
}
}
Результат выполнения кода:
Released: false
Remaining count: 3
Смотрите также
-
метод
countDown,
который уменьшает счетчик защелки -
метод
await,
который ожидает обнуления счетчика -
класс
CyclicBarrier,
который является переиспользуемым барьером -
класс
Semaphore,
который управляет доступом к ресурсам