Java线程通信核心是“通知”与“等待”,非数据传递;基础机制为wait/notify(需synchronized内调用),volatile+while适用于轻量状态通知,LockSupport提供无锁灵活阻塞,JUC高级工具类如CountDownLatch、CyclicBarrier等封装常见协作模式。

Java中线程通信的核心目标是协调多个线程对共享资源的访问,避免竞态条件,同时实现线程间的协作与状态同步。关键不在于“传数据”,而在于“通知”和“等待”——一个线程告诉另一个“你可以继续了”,或“我还没准备好,你先等等”。
wait/notify 是最基础的通信机制
这两个方法定义在 Object 类中,必须在 synchronized 方法或代码块内调用。它们依赖对象的内置锁(monitor):
- wait():让当前线程释放锁、进入该对象的等待队列,并暂停执行;直到其他线程调用 notify() 或 notifyAll()
- notify():唤醒等待队列中的一个线程(不保证哪一个);notifyAll() 唤醒所有等待线程
- ⚠️ 注意:被唤醒的线程不会立刻执行,它要重新竞争锁,拿到锁后才从 wait() 返回
- 经典场景:生产者-消费者模型中,缓冲区满时生产者 wait,空时消费者 wait
volatile + while 循环实现轻量级状态通知
当只需传递简单布尔状态(如“任务完成”“开关开启”),且无需释放锁、也不涉及复杂等待逻辑时,volatile 配合忙等待(spin-wait)是一种简洁选择:
- 声明一个 volatile boolean ready = false;,确保修改对所有线程可见
- 线程A设置 ready = true;,线程B用 while (!ready) Thread.yield(); 等待
- 适合延迟敏感、等待时间极短的场景;但长期空转浪费CPU,不能替代 wait/notify
LockSupport 提供更灵活的阻塞与唤醒
java.util.concurrent.locks.LockSupport 是JUC底层支持类,不依赖 synchronized,也不要求锁对象:
立即学习“Java免费学习笔记(深入)”;
- LockSupport.park():阻塞当前线程(类似 wait)
- LockSupport.unpark(Thread t):唤醒指定线程(类似 notify,但可提前唤醒,且无“丢失通知”问题)
- 每个线程都有一个隐式的许可(permit),park 消耗许可,unpark 添加许可;许可最多为1,重复 unpark 不叠加
- ReentrantLock、AQS 等都基于它实现,适合构建自定义同步器
高级工具类封装了常见通信模式
JUC 提供了语义明确、线程安全的高级通信组件,大幅降低出错概率:
- CountDownLatch:一个线程等待N个线程完成某件事(如初始化),用 countDown() 和 await()
- CyclicBarrier:多个线程互相等待,到达同一屏障点后一起继续,适合分阶段并行计算
- Exchanger:两个线程在指定点交换数据,典型用于流水线式协作
- Semaphore:控制并发访问数量,也可用于“信号量通信”,比如限制最多2个线程进入临界区
基本上就这些。选哪种方式,取决于你要解决的具体问题:是否需要释放锁?是否要精确控制唤醒哪个线程?是否涉及多线程协同步骤?弄清场景,再挑合适的工具,比死记语法更重要。











