Java线程间通信核心是共享数据与协作,常用方式包括:1.共享变量+wait/notify(需synchronized、while循环防虚假唤醒);2.BlockingQueue实现无锁生产者-消费者;3.CountDownLatch/CyclicBarrier控制阶段同步;4.Exchanger用于两线程交换数据。

Java 中线程间简单通信,核心在于让多个线程能安全地共享和交换数据,而不是各自跑各自的。最常用、最基础的方式是通过 共享变量 + 同步机制 配合 wait/notify 或 LockSupport 实现协作;JDK 5 之后也推荐使用 java.util.concurrent 包中的高级工具(如 BlockingQueue、CountDownLatch、Exchanger 等)来简化逻辑。
用 wait/notify 实现生产者-消费者模式
这是最经典的线程通信示例:一个线程生成数据(生产者),另一个线程消费数据(消费者),它们通过同一个对象的监视器锁协调执行顺序。
- 必须在 synchronized 块或方法中 调用 wait() 和 notify()/notifyAll()
- wait() 会释放锁并进入等待状态;notify() 唤醒一个等待线程,但不立即释放锁,被唤醒线程需重新竞争锁
- 务必用 while 循环判断条件(而非 if),防止虚假唤醒
示例关键片段:
synchronized (sharedList) {while (sharedList.isEmpty()) {
sharedList.wait(); // 等待有数据
}
int data = sharedList.remove(0);
System.out.println("消费:" + data);
sharedList.notifyAll(); // 通知生产者可以继续放
}
用 BlockingQueue 实现无锁式通信
BlockingQueue 是线程安全的队列,内部已封装了等待/唤醒逻辑,比手动 wait/notify 更简洁、不易出错。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- put() 在队列满时阻塞,take() 在队列空时阻塞
- 无需显式加锁或调用 wait/notify,适合生产者-消费者场景
- 常用实现类:ArrayBlockingQueue(有界)、LinkedBlockingQueue(可选有界)、SynchronousQueue(容量为 0,直接传递)
示例:
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);// 生产者:
queue.put(42); // 满则阻塞
// 消费者:
int x = queue.take(); // 空则阻塞
用 CountDownLatch 或 CyclicBarrier 控制阶段同步
当多个线程需要“齐步走”或“等全部就绪再一起开始”,这类通信不涉及数据传递,而是协调执行节奏。
- CountDownLatch:一次性倒计时门闩。比如主线程等待 3 个子任务全部完成后再继续
- CyclicBarrier:可重复使用的屏障。适合多轮协作(如并行计算每轮都需所有线程到达后才进入下一轮)
- 两者都支持超时等待和到达时触发 Runnable
示例(CountDownLatch):
CountDownLatch latch = new CountDownLatch(3);// 每个子线程最后调用:
latch.countDown();
// 主线程等待:
latch.await(); // 所有子线程完成才继续
用 Exchanger 在两个线程间直接交换数据
当恰好有两个线程需要成对交换数据(比如双缓冲处理),Exchanger 是专为此设计的轻量级工具。
- exchange(V x) 方法会阻塞,直到另一个线程也调用 exchange,然后双方交换对象
- 天然配对,线程数必须为 2,否则会一直等待
- 适合流水线中相邻阶段的双向数据交接
示例:
Exchanger<String> ex = new Exchanger<>();// 线程 A:
String aData = "from-A";
String fromB = ex.exchange(aData);
// 线程 B:
String bData = "from-B";
String fromA = ex.exchange(bData); // 此时双方拿到对方的数据

















