Exchanger 是 Java 中用于两个线程间成对同步交换数据的并发工具类,严格限制为两两配对、一次性原子交换,支持超时机制防止死锁,适用于双缓冲等双向协作场景。

Java 中的 Exchanger 是一个用于两个线程之间**成对同步交换数据**的并发工具类,适用于需要双向协作的场景(比如生产者-消费者配对、工作线程交换缓冲区等)。它不是“任意线程间广播”或“多线程共享”,而是严格限制为两个线程在屏障点等待并交换对象——一方调用 exchange() 阻塞,直到另一方也调用才完成交换。
Exchanger 的基本用法
创建 Exchanger 实例后,两个线程分别调用 exchange(V x) 方法传入自己的数据。该方法会阻塞当前线程,直到另一个线程也调用 exchange,然后双方原子性地交换对象并返回对方的数据。
- 如果只有一个线程调用,它会一直等待(可设超时避免死锁)
- 交换是一对一、一次性的:每次成功 exchange 后,Exchanger 可再次被复用,但必须仍是两两配对
- 泛型参数 V 表示交换的数据类型,类型由使用者统一约定
典型使用场景示例
常见于双缓冲处理:线程 A 填充缓冲区 bufferA,线程 B 消费 bufferB;两者在某个时刻交换引用,实现无缝切换。
Exchangerexchanger = new Exchanger<>(); int[] myBuffer = new int[1024]; // 线程 A:填充后交换 myBuffer = exchanger.exchange(myBuffer); // 交出已填好的,拿到对方刚消费完的 // 线程 B:消费后交换 myBuffer = exchanger.exchange(myBuffer); // 交出已消费完的,拿到对方刚填好的
注意:实际中需配合循环和状态控制,避免空指针或逻辑错位。
立即学习“Java免费学习笔记(深入)”;
带超时的 exchange 更安全
为防止因某一方异常退出导致另一方永久阻塞,推荐使用带超时的重载方法:
exchange(V x, long timeout, TimeUnit unit)- 超时抛出
TimeoutException,可做清理或重试 - 例如:
exchanger.exchange(data, 3, TimeUnit.SECONDS)
注意事项与限制
Exchanger 不是万能的数据共享方案,使用前需确认是否符合其设计契约:
- 只支持恰好两个线程参与一次交换;第三个线程调用会一直等待(无排队机制)
- 不保证交换顺序,但保证成对发生;若线程中断,会抛出
InterruptedException - 内部基于 CAS 和自旋优化,性能较好,但不适合高频短数据交换(相比队列可能略重)
- 不能替代 BlockingQueue、SynchronousQueue 等通用协调器,它是更专用的“镜像交换”原语
基本上就这些。Exchanger 简单但精准,用对了能写出清晰、低锁的双线程协作逻辑。










