Java多线程协作核心是状态感知与按需等待唤醒,非轮询;volatile适用于简单标志位可见性通知;wait/notify需synchronized+while防虚假唤醒;BlockingQueue等并发工具类面向场景封装更推荐。

Java 多线程协作与通信,核心是让线程“知道彼此的状态”并“按需等待或唤醒”,而不是靠空转轮询浪费 CPU。关键不在于有多少种方式,而在于每种方式解决什么场景、怎么用才安全。
共享变量 + volatile:轻量状态通知
适用于简单标志位(如开关、完成信号),不涉及复杂数据交换。
- volatile 保证可见性:一个线程修改后,其他线程能立即看到最新值,避免因 CPU 缓存导致的读旧值问题
- 不保证原子性:不能用于 count++ 这类复合操作;仅适合布尔开关、状态枚举等单次写入/读取场景
- 典型用法:主线程启动工作线程后,用 volatile boolean running = true 控制其循环执行;另一线程设为 false 即可优雅终止
wait/notify + synchronized:经典条件等待
这是最底层、最通用的协作机制,基于对象监视器,专为“等待某个条件成立”而设计。
- 必须在 synchronized 块中调用:否则抛 IllegalMonitorStateException
- 永远用 while 循环检查条件:防止虚假唤醒(spurious wakeup)——即使没被 notify,线程也可能被系统唤醒
- notify() 随机唤醒一个等待线程;notifyAll() 唤醒全部——生产者-消费者模型中推荐用 notifyAll(),避免死锁
- 示例逻辑:缓冲区满时,生产者 wait();消费者取走数据后,调用 notifyAll() 唤醒可能等待的生产者
高级并发工具类:面向场景封装
java.util.concurrent 提供了更易用、更健壮的协作组件,推荐优先使用。
立即学习“Java免费学习笔记(深入)”;
- BlockingQueue:天然适配生产者-消费者。put() 阻塞直到有空间,take() 阻塞直到有元素,内部已处理锁和唤醒逻辑
- CountDownLatch:适用于“一个线程等待多个线程完成”。比如主线程 await(),子任务执行完各自 countDown(),计数归零即放行
- CyclicBarrier:适用于“多个线程互相等待齐备后一起继续”。比如模拟并发压测,所有线程就位后同时发起请求
- Phaser / Exchanger:进阶场景,如分阶段同步、线程间直接交换数据
管道流与 join:特定用途补充
不是通用通信手段,但在限定场景下简洁有效。
- PipedInputStream / PipedOutputStream:适合线程间传递字节流数据,如内存中直接转发文件内容,避免临时落盘
- join():用于“当前线程等待另一线程结束”,本质是阻塞调用方,不涉及共享状态或条件判断,适合串行化依赖


















