[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-mnogopotochnost-v-chem-zaklyuchayutsya-razlichiya-mezhdu-cyclicbarrier-i-countdownlatch":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":20,"progress":21,"seo":22},258,"v-chem-zaklyuchayutsya-razlichiya-mezhdu-cyclicbarrier-i-countdownlatch",8,"mnogopotochnost","Многопоточность","🔀","В чем заключаются различия между CyclicBarrier и CountDownLatch?","\u003C!-- grade: 4\u002F5 — хорошее сравнение с примерами из жизни, но нет примера кода -->\n\nОба класса из пакета `java.util.concurrent` являются **синхронизаторами**, позволяющими координировать работу нескольких потоков. Однако они различаются по модели использования.\n\n### CountDownLatch (замок с обратным отсчётом)\n\n`CountDownLatch` позволяет одному или нескольким потокам ждать, пока набор операций в других потоках не будет завершён. Счётчик уменьшается вызовом `countDown()` и не может быть сброшен -- **одноразовый**.\n\n```java\nCountDownLatch latch = new CountDownLatch(3); \u002F\u002F Ждём 3 события\n\n\u002F\u002F Рабочие потоки:\nlatch.countDown(); \u002F\u002F Уменьшает счётчик на 1\n\n\u002F\u002F Ожидающий поток:\nlatch.await(); \u002F\u002F Блокируется, пока счётчик не станет 0\n```\n\n### CyclicBarrier (циклический барьер)\n\n`CyclicBarrier` -- точка синхронизации, где указанное количество потоков **встречается** и одновременно продолжает выполнение. Барьер **многоразовый** -- после «слома» он автоматически сбрасывается.\n\n```java\nCyclicBarrier barrier = new CyclicBarrier(3, () -> {\n    System.out.println(\"Все 3 потока на месте, продолжаем!\");\n});\n\n\u002F\u002F Каждый из 3 потоков:\nbarrier.await(); \u002F\u002F Блокируется, пока все 3 не вызовут await()\n```\n\n### Сравнение\n\n| Характеристика | `CountDownLatch` | `CyclicBarrier` |\n|---|---|---|\n| Повторное использование | **Нет** (одноразовый) | **Да** (сбрасывается автоматически) |\n| Кто уменьшает счётчик | Любой поток вызовом `countDown()` | Сам поток вызовом `await()` |\n| Кто ожидает | Потоки, вызвавшие `await()` | Все потоки-участники (взаимное ожидание) |\n| Один поток может сделать `countDown()` несколько раз | **Да** | Нет (один поток -- один `await()`) |\n| Опциональное действие при завершении | Нет | Да (`barrierAction` в конструкторе) |\n| Модель | «Ожидание завершения N событий» | «Встреча N потоков в точке» |\n| Обработка ошибок | Нет специальной | `BrokenBarrierException`, если один из потоков прерван или вышел по таймауту |\n\n### Примеры применения\n\n\u003Cdetails>\n\u003Csummary>Пример: CountDownLatch -- ожидание готовности сервисов\u003C\u002Fsummary>\n\n```java\npublic class ServiceStartup {\n    public static void main(String[] args) throws InterruptedException {\n        int serviceCount = 3;\n        CountDownLatch latch = new CountDownLatch(serviceCount);\n\n        \u002F\u002F Запуск сервисов\n        for (String name : List.of(\"БД\", \"Кэш\", \"Очередь\")) {\n            new Thread(() -> {\n                System.out.println(\"Запуск сервиса: \" + name);\n                try { Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 3000)); }\n                catch (InterruptedException e) { return; }\n                System.out.println(name + \" готов\");\n                latch.countDown();\n            }).start();\n        }\n\n        \u002F\u002F Основной поток ждёт, пока все сервисы не стартуют\n        latch.await();\n        System.out.println(\"Все сервисы запущены, приложение готово!\");\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Пример: CyclicBarrier -- параллельная обработка с фазами\u003C\u002Fsummary>\n\n```java\npublic class ParallelPhases {\n    public static void main(String[] args) {\n        int workers = 3;\n        CyclicBarrier barrier = new CyclicBarrier(workers, () ->\n            System.out.println(\"--- Все потоки завершили фазу ---\"));\n\n        for (int i = 0; i \u003C workers; i++) {\n            final int id = i;\n            new Thread(() -> {\n                try {\n                    for (int phase = 1; phase \u003C= 3; phase++) {\n                        System.out.println(\"Поток \" + id + \": фаза \" + phase);\n                        Thread.sleep(ThreadLocalRandom.current().nextInt(500, 1500));\n                        barrier.await(); \u002F\u002F Ждём остальных\n                        \u002F\u002F Барьер автоматически сбрасывается для следующей фазы\n                    }\n                } catch (InterruptedException | BrokenBarrierException e) {\n                    e.printStackTrace();\n                }\n            }).start();\n        }\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n> **Аналогия из жизни.** `CountDownLatch` -- это сбор экскурсионной группы: гид ждёт, пока не соберётся нужное количество человек, и экскурсия начинается один раз. `CyclicBarrier` -- это забег с этапами: все бегуны ждут друг друга на каждом контрольном пункте и только потом бегут дальше, и так на каждом этапе.\n\n> **На собеседовании.** Три ключевых отличия: (1) `CountDownLatch` одноразовый, `CyclicBarrier` многоразовый; (2) `CountDownLatch` разделяет «отмечающие» и «ожидающие» потоки, `CyclicBarrier` -- все потоки равноправны; (3) `CyclicBarrier` поддерживает `barrierAction`. Также стоит упомянуть `Phaser` (Java 7) как более гибкую альтернативу обоим синхронизаторам.","","middle",[15,16,17,18,19],"синхронизатор","барьер","CountDownLatch","CyclicBarrier","concurrency",[],null,{"title":23,"description":24,"ogTitle":25,"ogDescription":26,"keywords":27,"schemaAnswer":32,"featuredSnippetReady":33},"CyclicBarrier vs CountDownLatch в Java — Gymterview","CountDownLatch — одноразовый замок с обратным отсчётом. CyclicBarrier — многоразовый барьер синхронизации потоков. Главное отличие — повторное использование.","CyclicBarrier vs CountDownLatch — одноразовый и многоразовый","CountDownLatch — одноразовый: после достижения нуля повторно использовать нельзя. CyclicBarrier — многоразовый барьер с опциональным действием.",[28,29,30,31],"CyclicBarrier vs CountDownLatch","CountDownLatch Java","CyclicBarrier Java","синхронизатор потоков","CountDownLatch — одноразовый замок: потоки ждут, пока счётчик не достигнет нуля. CyclicBarrier — многоразовый барьер: потоки встречаются в точке синхронизации и освобождаются одновременно. Главное отличие: CountDownLatch можно использовать лишь один раз, CyclicBarrier — неоднократно.",true]