В чем разница между CountDownLatch и CyclicBarrier
Что проверяют
Понимаете ли вы, что это два разных сценария координации, а не просто «одноразовая и многоразовая версия одного и того же». Следом обычно спрашивают, что будет, если один из потоков упал до countDown() или await(), и чем можно заменить оба класса.
Как отвечать
Начните с ролей потоков, потом переходите к повторному использованию:
CountDownLatch: счётчик, который уменьшают одни потоки, а ждут другие.countDown()не блокирует,await()блокирует до нуля. Сбросить счётчик нельзя, защёлка одноразовая. Типичные случаи: главный поток ждёт, пока N воркеров закончат инициализацию, или N потоков ждут общего сигнала «старт» от защёлки на единицу;CyclicBarrier: точка сбора для фиксированной группы потоков. Каждый участник вызываетawait()и блокируется, пока не соберутся всеparties. Затем выполняется необязательныйbarrierAction(его запускает последний пришедший поток), и барьер сам возвращается в исходное состояние для следующей фазы;- сломанный барьер: если участник прерван или вышел по таймауту, барьер переходит в состояние broken, остальные получают
BrokenBarrierException. Вернуть его в строй можно черезreset(); Phaser: гибкая замена обоим, умеет несколько фаз и динамическую регистрацию участников черезregister()иarriveAndDeregister().
Короткая формула: в защёлке ждущие и считающие это разные потоки, в барьере все участники равноправны и ждут друг друга. Для задачи «запустить N асинхронных операций и дождаться всех» в современном коде чаще берут CompletableFuture.allOf() или invokeAll() у ExecutorService.
Где спотыкаются
Ставят countDown() в конце блока try без finally. Одно исключение в воркере, и главный поток висит на await() вечно. Правильно: countDown() в finally, а await() с таймаутом.
Запускают участников барьера в пуле, где потоков меньше, чем parties. Барьер никогда не откроется: занятые потоки ждут на await(), а оставшиеся задачи стоят в очереди.
Пишут barrier.await() прямо в лямбде Runnable. Такой код не скомпилируется: метод бросает проверяемые InterruptedException и BrokenBarrierException, их нужно обработать.