CountDownLatch适用于一次性等待所有操作完成,不可重置;CyclicBarrier适用于多线程循环协同,可重置并支持屏障中断与回调。二者语义不同,不可互换。

CountDownLatch 适合“等待一组操作全部完成”
它是一次性使用的计数器,初始化时指定一个 count,每次调用 countDown() 就减一,调用 await() 的线程会阻塞直到计数归零。常见于:主线程等所有子任务跑完再继续、服务启动时等待多个组件初始化完毕。
注意点:
-
CountDownLatch不能重置,一旦计数到 0,后续所有await()都立即返回 - 没有“唤醒所有等待线程后自动重置”的机制,所以不适合循环场景
- 如果某线程调用
await()后被中断,会抛InterruptedException,需自行处理
CyclicBarrier 适合“多线程分阶段协同执行”
它更像一个“集合点”,多个线程各自执行一段逻辑后,在 await() 处等待彼此到达;当最后一个线程到达,所有线程同时被释放,并可选择执行一个 Runnable(如汇总统计)。典型场景:并行计算分片处理 + 汇总、多玩家准备就绪后开始游戏回合。
关键行为:
媒体包提供了可管理各种媒体类型的类。这些类可提供用于执行音频和视频操作。除了基本操作之外,还可提供铃声管理、脸部识别以及音频路由控制。本文说明了音频和视频操作。 本文旨在针对希望简单了解Android编程的初学者而设计。本文将指导你逐步开发使用媒体(音频和视频)的应用程序。本文假定你已安装了可开发应用程序的Android和必要的工具,同时还假定你已熟悉Java或掌握面向对象的编程概念。感兴趣的朋友可以过来看看
立即学习“Java免费学习笔记(深入)”;
-
CyclicBarrier可重复使用,计数归零后自动重置为初始值 - 支持带超时的
await(long timeout, TimeUnit unit),超时后会抛TimeoutException并打破屏障 - 任一线程在
await()时被中断或超时,整个屏障进入broke状态,其他等待线程也会收到BrokenBarrierException
别把它们当“可互换的等待工具”用
表面上都让线程等,但设计意图完全不同:
- 用
CountDownLatch实现“多线程等一个信号”很简单,但反过来模拟CyclicBarrier的循环协作就得自己加锁 + 重置逻辑,容易出错 - 用
CyclicBarrier做一次性等待也可以,但它的异常传播机制(BrokenBarrierException)和重入特性在单次场景里是冗余负担 - 性能上差异不大,但语义误用会导致调试困难——比如看到
BrokenBarrierException却用了CountDownLatch,说明代码逻辑和工具选型不匹配
一个容易忽略的细节:线程到达顺序不影响 CyclicBarrier 行为
CyclicBarrier 不关心谁先到、谁后到,只关心“是否凑够 parties 个”。但要注意:Runnable 回调(如果设置了)是由最后一个到达的线程执行的,不是由某个固定线程执行。这意味着:
- 回调里不要做耗时操作,否则会拖慢最后一个线程,进而影响下一轮等待的启动
- 回调中若抛异常,会导致所有等待线程收到
BrokenBarrierException - 如果想在回调里安全更新共享状态,得确保该状态本身是线程安全的,或者回调已处于临界区保护下







