Java线程间通信方式需按场景选择:生产者-消费者优先用BlockingQueue;多线程等待同一事件选CountDownLatch或CyclicBarrier;单向流式通信用PipedStream或Exchanger;轻量通知用volatile+轮询或CompletableFuture。

Java 线程间通信方式有多种,选择哪一种取决于具体场景的协作需求、数据流向、实时性要求和代码可维护性。没有“万能方案”,但有清晰的匹配逻辑。
按协作模式选:生产者-消费者类场景用 wait/notify 或 BlockingQueue
这是最常见也最容易出错的通信类型(比如消息入队、日志写入、任务分发)。关键特征是:一个线程生成数据,另一个线程消费数据,双方需感知对方状态(满/空)并阻塞等待。
- 推荐优先用 BlockingQueue(如 LinkedBlockingQueue、ArrayBlockingQueue):封装了线程安全的 put/take 操作,自动处理阻塞与唤醒,代码简洁、不易出错,适合大多数业务场景。
- 需要精细控制锁或复用已有对象锁时,用 synchronized + wait/notifyAll:必须用 while 循环检查条件(防虚假唤醒),notifyAll 比 notify 更安全;适用于对同步粒度敏感或已有 synchronized 设计的遗留系统。
按同步目标选:多线程等待同一事件用 CountDownLatch 或 CyclicBarrier
当目标不是传递数据,而是协调执行时机,比如“所有子任务完成后再汇总”或“多个线程准备就绪后同时开始”:
- CountDownLatch(一次性倒计时):适合“一个线程等多个线程完成”,例如主线程等待 3 个下载线程全部结束再触发 UI 更新。
- CyclicBarrier(可重用栅栏):适合“多个线程互相等待、共同推进”,例如模拟赛跑——所有运动员准备完毕后一起起跑;支持到达时执行回调动作。
按数据传递方向选:单向流式通信用 PipedStream 或 Exchanger
当两个线程之间要像管道一样连续传输字节或字符数据(非简单状态或对象),或需交换一次数据:
立即学习“Java免费学习笔记(深入)”;
- PipedInputStream / PipedOutputStream(或 PipedReader / PipedWriter):适合内存中流式中转,比如线程 A 生成压缩数据,线程 B 实时解压,避免临时文件;注意必须先 connect,且读写线程不能是同一个。
- Exchanger<V>:适用于两个线程在某个汇合点交换数据(如双缓冲场景),双方都调用 exchange() 后才继续执行,天然成对、强约束。
按轻量通知选:状态变更广播用 volatile + 循环检查 或 CompletableFuture
当通信只是“告诉对方:我完成了”或“状态已改变”,不涉及复杂同步或数据搬运:
- volatile 布尔变量 + while 循环轮询:极简,但只适用于低频、延迟不敏感场景(如关闭信号);避免高频轮询浪费 CPU,必要时配合 Thread.yield() 或短时 sleep。
- CompletableFuture:适合异步链式协作,比如线程 A 计算结果后自动触发线程 B 处理,支持异常传播、组合、超时控制,现代异步编程首选。


















