Что такое CyclicBarrier в Java?

«Что такое CyclicBarrier в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

CyclicBarrier — это синхронизатор из пакета java.util.concurrent, который заставляет набор потоков ждать друг друга в определенной точке (барьере), прежде чем продолжить выполнение.

Ключевые характеристики:

  • Цикличность: После того как ожидающие потоки достигнут барьера и будут освобождены, барьер сбрасывается и может быть использован повторно.
  • Действие при достижении барьера: Можно задать Runnable-задачу (барьерное действие), которая выполняется один раз после того, как последний поток достигнет барьера, но до того, как все потоки будут разблокированы.

Основные методы:

  • await(): Поток блокируется до достижения барьера заданным количеством потоков.
  • await(long timeout, TimeUnit unit): То же, но с таймаутом.
  • reset(): Принудительно сбрасывает барьер в исходное состояние, что приводит к BrokenBarrierException в ожидающих потоках.

Пример: Три потока выполняют первую фазу работы, ждут друг друга, а затем начинают вторую фазу.

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
    public static void main(String[] args) {
        int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, 
            () -> System.out.println("--- Все потоки достигли барьера. Запускаем вторую фазу. ---"));

        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            new Thread(() -> {
                try {
                    System.out.println("Поток " + threadId + " выполняет первую фазу.");
                    Thread.sleep((long) (Math.random() * 1000)); // Имитация работы
                    barrier.await(); // Ожидание других потоков

                    System.out.println("Поток " + threadId + " выполняет вторую фазу.");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

Отличие от CountDownLatch: CountDownLatch — одноразовый, потоки ждут события; CyclicBarrier — многоразовый, потоки ждут друг друга.