Exchanger 是 Java 并发包中专用于两个线程间同步交换数据的工具类,通过成对阻塞与原子交换机制实现严格二元配对,支持超时控制和重复使用,适用于双缓冲、生产者-消费者协同等场景。

Exchanger 是 Java 并发包(java.util.concurrent)中一个专门用于**两个线程之间同步交换数据**的工具类。它适用于“成对协作”的场景,比如一个线程生成数据、另一个线程消费数据,双方必须在某个点“碰头”并交换内容,且只有两个线程能参与这次交换。
Exchanger 的基本用法
创建一个 Exchanger<V> 实例,泛型 V 表示要交换的数据类型。每个线程调用 exchange(V) 方法:
- 调用后线程会阻塞,直到另一个线程也调用同一个 Exchanger 的 exchange();
- 一旦配对成功,两个线程各自拿到对方传入的值,然后同时继续执行;
- 如果其中一个线程提前退出或超时未配对,另一个线程会一直等待(除非使用带超时的重载方法)。
示例:两个线程分别持有缓冲区,定期交换内容:
Exchanger<String> exchanger = new Exchanger<>();
new Thread(() -> {
String data = "from-A";
try {
String other = exchanger.exchange(data); // 阻塞,直到B线程也调用
System.out.println("A received: " + other);
} catch (InterruptedException e) { ... }
}).start();
<p>new Thread(() -> {
String data = "from-B";
try {
String other = exchanger.exchange(data);
System.out.println("B received: " + other);
} catch (InterruptedException e) { ... }
}).start();注意配对的严格性:只能两两交换
Exchanger 不支持多个线程参与同一次交换。如果第三个线程调用 exchange(),它不会和前两个中的某一个配对,而是等待**另一个尚未配对的线程**——也就是说,Exchanger 总是以“二元组”为单位工作:
- 第一次调用和第二次调用组成一对;
- 第三次和第四次组成下一对;
- 若线程数为奇数,最后一个线程会一直阻塞,除非被中断或超时;
- 不能复用同一个 Exchanger 实例让 A↔B、A↔C 同时发生——那是不同配对,需各自等待新伙伴。
处理超时与中断
避免无限等待,推荐使用带超时的 exchange(V, timeout, unit):
立即学习“Java免费学习笔记(深入)”;
- 超时后抛出
TimeoutException,调用方可以决定重试、记录日志或清理资源; - 线程被中断时抛出
InterruptedException,应正确响应中断(如恢复中断状态、退出循环); - 注意:超时或中断后,该次交换失败,但 Exchanger 本身仍可继续用于后续配对。
典型适用场景
Exchanger 不是万能工具,适合明确满足“双线程协作+数据互换”模式的场景:
- 双缓冲机制:线程 A 填充 buffer1,线程 B 处理 buffer2;二者交换引用后角色互换;
- 生产者-消费者成对协作:比如一个线程采集传感器数据,另一个线程做实时分析,按批次交换数据块;
- 测试或模拟协同行为:验证两个组件在同步点的数据一致性。
不适用于:多线程广播、异步消息传递、需要排队或缓冲的场景(此时应选 BlockingQueue 或 Phaser 等)。



















