Exchanger 是专为双线程原子交换引用设计的轻量同步点,不排队、不缓存、不支持多线程,必须配对使用并配合超时、异常处理与双缓冲机制。

Exchanger 不是万能的消息通道,而是专为两个线程“面对面交接”设计的轻量同步点。它不排队、不缓存、不识别身份,只做一件事:等另一个线程到场,然后原子交换引用。用对了,零拷贝、低延迟;用错了,一个线程挂起,整个协作链就断。
必须严格双线程配对,别把它当队列用
Exchanger 只认“当前阻塞的两个线程”,不记名字、不存历史。这意味着:
- 第三个线程调用 exchange() 会无限等待——前两轮已交换完毕,槽位清空,无人响应
- 线程 A 异常退出(如抛出 RuntimeException),线程 B 就卡在 exchange() 上,永远等不到回应
- 在线程池中复用同一个 Exchanger 实例,无法保证“上一轮的 A 还在等 B”,协作关系彻底断裂
- 它不是 BlockingQueue 或 SynchronousQueue 的替代品,不支持多生产者或多消费者
交换动作要快,耗时逻辑必须移出来
exchange() 是同步屏障,不是执行入口。它的职责只是移交引用,不是干活。
- 把数据准备好再调用:先填满 buffer,再 exchange(buffer);不要在 exchange 内部边读边写或做序列化
- 避免触发 GC 或长暂停:exchange 中若发生大对象分配或 Full GC,会拖慢配对线程,放大端到端延迟
- 典型做法是配合双缓冲(front/back)循环使用,exchange 就是切换控制权的开关,本身毫秒级完成
超时和中断不能忽略,得主动兜底
无超时的 exchange(V) 在生产环境风险极高。务必用带参版本,并正确处理异常:
- 优先选用 exchange(V, 3, TimeUnit.SECONDS),超时后抛 TimeoutException,可降级、重试或释放资源
- 捕获 InterruptedException 后,必须恢复中断状态:Thread.currentThread().interrupt()
- 无论超时还是中断,都应触发清理:关闭临时资源、归还 buffer、上报监控指标
- 别假设“对方一定在等你”——线程生命周期错位很常见,超时是保命机制,不是可选项
数据类型与对象生命周期要双方约定清楚
泛型只管编译期类型一致,运行时语义还得靠协作规范:
- 允许传 null,但若一方传 null、另一方直接 dereference,立刻 NPE——建议用哑值(如 new byte[0])或 Optional 封装
- 交换的是引用,不是副本。确保双方不共享同一对象实例,否则读写竞争仍需额外同步
- 收到对方 buffer 后,不要假设它“干净可用”:可能被对方复用、修改过,需按协议重置或校验
- 图像/音视频等场景中,常固定两块 buffer 循环复用,exchanger 就是那个“换手”信号,语义清晰、内存稳定

















