Exchanger 是专为双线程配对交换设计的无锁工具,要求严格两两匹配、轻量调用、显式处理中断与超时,禁止在线程池中复用或在 exchange() 内执行耗时操作。

Exchanger 是 Java 并发包中专为两个线程设计的原子交换工具,它不靠锁、不靠队列,而是用“手拉手”配对机制实现零拷贝、低延迟的数据移交。关键不在“怎么交换”,而在于“谁和谁交换、何时交换、出错怎么收场”。
双线程严格配对是硬性前提
Exchanger 只认“当前到达的两个线程”,不记录身份、不维护历史。一个实例被多个线程轮番调用,极易导致错配或永久阻塞:
- 第三个线程调用 exchange() 会无限等待——因为前两个已完成交换,槽位已清空,无人响应
- 线程 A 完成一轮后提前退出(如异常 return),线程 B 在 exchange() 处挂起,整个流程卡死
- 在线程池中复用同一个 Exchanger 实例,无法保证“上一轮的 A 还在等 B”,协作关系断裂
交换动作必须轻量且可控
exchange() 是同步点,不是执行点。所有耗时逻辑(如序列化、IO、复杂计算)必须放在 exchange() 调用前后,而非其中:
- 把 buffer 填满后再调用 exchange(buffer),而不是在 exchange() 内部边读边写
- 避免在 exchange() 中触发 GC 或长时间停顿,否则会拖慢配对线程,放大端到端延迟
- 推荐始终使用带超时的版本:exchange(x, 3, TimeUnit.SECONDS),超时后抛 TimeoutException,便于主动降级或重试
数据类型与空值需双方约定
泛型 T 保证编译期类型一致,但运行时仍需注意语义一致性:
- 允许交换 null,但若一方传 null、另一方期待非 null 对象,可能引发 NPE —— 建议初始化用哑值(如 new byte[0])或封装为 Optional
- 缓冲区场景中,交换的是引用而非内容,确保双方不共享同一对象实例,避免读写竞争
- 图像处理、音视频流水线等典型用法中,常配合两块固定 buffer(front/back)循环复用,exchanger.exchange() 就是切换控制权的开关
中断与异常必须显式处理
线程被中断时,exchange() 会立即抛 InterruptedException,此时交换未发生,数据仍在原线程手中:
- 捕获后务必恢复中断状态:Thread.currentThread().interrupt()
- 不要忽略 InterruptedException,否则协作协议被破坏,配对线程可能因未收到响应而持续等待
- 超时和中断都应触发清理逻辑,比如释放 buffer、关闭资源、上报监控指标

















