exchanger是专为两个线程在同步点严格配对、原子交换数据设计的协作机制,要求双方同时到达才能触发交换,不缓存、不广播、不支持多线程,核心价值在于“同时阻塞、同时释放、原子交换”。

Exchanger 不是数据“传输”工具,而是两个线程在同步点严格配对交换数据的协作机制。它不保证顺序、不缓存数据、不支持广播或异步通知,核心价值在于“同时阻塞、同时释放、原子交换”——真正实现线程间状态协同。
明确适用边界:只服务成对线程的双向协作
Exchanger 的设计前提就是「恰好两个活跃线程」参与一次交换。多一个线程调用,它就卡住等配对;少一个线程启动,另一个就无限挂起。典型匹配场景包括:
- 双缓冲渲染:一个线程往 backBuffer 写像素,另一个线程从 frontBuffer 读并显示,交换引用后角色互换
- 加密/解密流水线:线程 A 加密一块数据后交给线程 B 解密,B 处理完再把结果交还 A 做后续封装
- 回合制协同:如模拟网络握手,A 发请求后必须等 B 返回确认,B 也必须等 A 提供上下文才发响应
交换动作本身即同步点:无需额外加锁
调用 exchange(V x) 的瞬间,线程就进入同步等待状态。JVM 底层通过 CAS 和队列管理确保:只要双方都抵达,交换动作是原子的,返回值一定是对方传入的对象引用,不存在中间态或数据撕裂。这意味着:
- 不需要 synchronized 或 ReentrantLock 包裹 exchange() 调用
- 交换前后可直接操作各自拿到的数据,无需担心竞态(前提是对象本身线程安全或仅单线程访问)
- 若交换的是数组或集合,注意避免双方误改同一实例——建议每次交换新对象,或明确约定只读/只写分工
超时控制是生产环境刚需
无限等待在真实系统中风险极高。网络抖动、线程异常退出、逻辑分支遗漏都可能导致配对失败。务必使用带超时的重载:
- exchange(x, 3, TimeUnit.SECONDS):超时后抛 TimeoutException,可捕获后执行降级逻辑(如重试、日志告警、切换备用缓冲区)
- 不要依赖返回 null 判断失败——超时抛异常,不是返回 null
- 超时时间需结合业务周期设定:双缓冲场景一般设为单次填充/处理耗时的 1.5~2 倍
泛型与生命周期必须严格对齐
两个线程使用同一个 Exchanger 实例时,类型和存活周期必须一致:
- 声明时用具体泛型,例如 Exchanger
,避免原始类型或泛型擦除导致运行时 ClassCastException - 确保两个线程真正并发执行:主线程启动子线程后不能立即 exit,可用 CountDownLatch 等协调启动时机
- 若需多次交换,复用同一 Exchanger 实例完全可行,但每次传入的数据对象应独立——别让线程 A 修改了 buffer 后,线程 B 下次拿到的还是那个被改过的旧引用











