exchanger 是专为两个线程设计的双向交换工具,通过汇合即交换机制原子性互换对象引用;仅支持严格配对,第三线程会无限等待;交换的是引用而非深拷贝,需配合超时保护,典型应用为双缓冲流水线。

Exchanger 是 Java 并发包中专为两个线程设计的双向数据交换工具,它不靠锁、不依赖队列,而是通过“汇合即交换”的机制,在两个线程到达同一同步点时原子性地互换对象引用。它的本质不是消息传递,而是协作移交——双方都交出一个值,也同时拿到对方的值。
双线程配对是硬性前提
Exchanger 只接受且仅能处理恰好两个活跃线程的 exchange() 调用。第三个线程调用会无限等待(除非设超时),因为内部没有缓冲、不支持轮转或广播。这种严格配对天然规避了多线程竞争问题,但也意味着你必须在设计阶段就明确限定协作角色:
- 启动前确保只有两个线程参与,避免误启后台任务或监控线程意外调用 exchange()
- 若某线程提前退出(如异常终止),另一线程将卡在 exchange() 上,需配合超时或中断机制兜底
- 不适合动态增减协作方的场景;如需弹性扩展,应考虑 SynchronousQueue 或自定义协调器
交换时机决定性能与语义
exchange() 是阻塞点,也是协作节奏的锚点。它本身不执行业务逻辑,只做引用交换,因此耗时应极短。实际性能优势正来自这个轻量特性:
- 交换的是对象引用,不是深拷贝——适合大缓冲区(如 byte[])、重计算结果等场景,避免内存复制开销
- 不要在 exchange() 调用前后夹带耗时操作(如 I/O、复杂计算),否则会拖慢配对线程,放大延迟毛刺
- 典型节奏是“准备→交换→处理”,例如:线程 A 填满 bufferA 后立即 exchange(bufferA),拿到 bufferB 后开始下一轮填充
必须启用超时保护生产环境
无参 exchange(V x) 在单点故障时会导致线程永久挂起,生产系统中不可接受。推荐统一使用带超时的重载方法:
- 设置合理 timeout(如 500ms~2s),既容许调度抖动,又能在异常时快速失败
- 捕获 TimeoutException 后可记录告警、重试、降级或主动关闭协作流
- InterruptedException 须正确传播:调用 Thread.currentThread().interrupt() 恢复中断状态,避免掩盖协作中断信号
典型双缓冲流水线示例
以图像帧处理为例,两个线程复用两块缓冲区,通过 Exchanger 协调交接:
- 线程 A(预处理):填充 frontBuffer → exchange(frontBuffer) → 拿到 backBuffer → 清空并复用 backBuffer
- 线程 B(后处理):消费 backBuffer → exchange(backBuffer) → 拿到 frontBuffer → 处理后释放 frontBuffer
- 全程无锁、无额外对象分配、无读写冲突——因为任一时刻,每块 buffer 至多被一个线程写,另一个线程正在处理另一块











