exchanger是java并发包中专为两个线程双向交换数据设计的轻量级同步工具,要求严格配对、一次交换、无内部缓冲,适用于双缓冲、生产者-消费者镜像等对等协作场景。

Exchanger 是 Java 并发包(java.util.concurrent)中一个轻量级的线程间协作工具,专为成对线程双向交换数据设计。它不适用于多线程轮换或广播场景,但在双工作线程(如“生产者-消费者”镜像结构、流水线双阶段处理)中移交数据时,能避免锁、队列和内存可见性问题,实现零拷贝、低延迟的同步移交。
Exchanger 的核心行为特点
它要求两个线程同时到达 exchange() 点才会完成交换,任一线程先到必须阻塞等待另一方;若一方超时或中断,另一方会抛出异常并解除阻塞。这种“手拉手”机制天然保证了数据移交的原子性和配对性。
- 不是“发送-接收”,而是“交换”:双方都提供一个对象,也各自获得对方的对象
- 类型安全:泛型参数
Exchanger<t></t>确保交换数据类型一致 - 无内部缓冲:不缓存历史数据,每次交换都是即时一对一
- 线程安全:无需额外同步,内部基于 CAS 和 LockSupport 实现
典型双线程协作模式示例
比如一个图像处理流水线:线程 A 做预处理(缩放/灰度),线程 B 做后处理(边缘检测/滤波)。两者交替使用两块缓冲区(bufferA、bufferB),通过 Exchanger 协调交接:
一款AI工具,主要用于Monitor and clean up invalid Codex authentication files in CPA. Check quota status, disable files returning 401 errors, and perform dual verification before deletion.,适合需要提升相关任务效率的用户。
- 线程 A 处理完 bufferA 后,调用
exchanger.exchange(bufferA),挂起等待 - 线程 B 此时也完成上一轮处理,调用
exchanger.exchange(bufferB),双方立即交换引用 - A 获得 bufferB 进入下一轮预处理,B 获得 bufferA 开始后处理
这样既复用内存、避免 GC 压力,又杜绝了读写竞争——因为同一时刻只有一方持有某块 buffer 的写权限,另一方正处理另一块。
使用时的关键注意事项
Exchanger 表面简单,但误用易导致死锁或逻辑错乱:
- 必须严格双线程配对:若第三个线程也调用 exchange(),它将无限等待(因无配对者),整个流程卡死
- 避免在 exchange() 中执行耗时操作:交换本身应是瞬时的,否则会拖慢配对线程,放大响应延迟
- 注意 null 安全:可交换 null,但需双方约定是否允许;建议初始化时传非 null 哑值,或用 Optional 封装
-
超时控制推荐启用:用
exchange(V x, long timeout, TimeUnit unit)防止单点故障导致全局阻塞
与 BlockingQueue 或 SynchronousQueue 对比
当只有两个线程且数据流向固定双向时,Exchanger 比队列更高效:
- 无队列头尾操作开销,无容量管理逻辑
- 无额外对象封装(如 Queue 的 Node 节点)
- 语义更精准:明确表达“我处理完了,换你来;你也处理完了,换我来”
- SynchronousQueue 虽也是一对一,但它是单向传递,且依赖生产者/消费者角色分离;Exchanger 更适合对等协作场景(如双工通信、乒乓缓冲)










