Exchanger 是 Java 并发包中专为两个线程配对交换数据设计的轻量级同步工具,通过“手拉手”会合机制原子性交换对象引用,支持泛型、无内部缓冲、可重用,适用于双缓冲等高频数据流转场景。

Exchanger 是 Java 并发包中专为两个线程配对交换数据设计的轻量级同步工具。它不依赖锁、队列或共享变量,而是通过“手拉手”式会合机制,让双方在线程安全的前提下,原子性地交换对象引用——既高效又语义清晰。
理解 Exchanger 的核心行为
它不是单向发送,也不是广播或轮转;它强制要求两个线程同时调用 exchange() 才能完成一次交换。任一线程先到,就会阻塞等待另一方。一旦配对成功,双方立即互换引用,各自拿到对方传来的对象后继续执行。
- 交换的是对象引用,不是深拷贝,适合大缓冲区(如
byte[]),零内存冗余 - 泛型确保类型安全,编译期即可校验
- 无内部缓冲,不缓存历史数据,每次都是即时一对一
- 同一实例可被多对线程重复使用,但每次只服务两个线程
基础用法:启动两个线程完成一次交换
声明一个泛型 Exchanger 实例,两个线程分别调用 exchange(data):
- 线程 A 传入
"Data from A",挂起等待 - 线程 B 传入
"Data from B",触发交换 - A 收到
"Data from B",B 收到"Data from A"
注意:返回值是对方的数据,不是自己传入的原始值,业务逻辑中切勿误判。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
生产环境必须加超时和异常处理
不带超时的 exchange(data) 在某线程异常退出或卡死时,会导致另一方永久阻塞。务必使用带超时的重载版本:
- 调用
exchanger.exchange(data, 3, TimeUnit.SECONDS) - 捕获
TimeoutException做降级或重试 - 捕获
InterruptedException后恢复中断状态:Thread.currentThread().interrupt()
典型实用场景:双缓冲轮换
图像渲染、音视频处理等高频数据流转场景中,用两块缓冲区 + Exchanger 可避免锁和 GC 压力:
- 线程 A(渲染)填满
backBuffer后调用exchanger.exchange(backBuffer) - 线程 B(显示)用完
frontBuffer后调用exchanger.exchange(frontBuffer) - 交换后,A 拿到刚显示完的
frontBuffer继续绘制,B 拿到刚渲染好的backBuffer准备显示 - 全程无竞争、无复制、内存恒定
为什么不用 BlockingQueue 或 SynchronousQueue?
在严格双线程配对场景下,Exchanger 更优:
- 内存开销更低:只维护两个引用,无队列节点或内部缓冲
- 语义更直接:“我要和对面那个线程换东西”,代码意图一目了然
- 避免了 SynchronousQueue 中可能发生的线程匹配不确定性(尤其在多线程共用时)


















