exchanger 是专为两个线程设计的轻量级同步工具,通过 exchange() 实现一对一、即时、零拷贝的对象引用交换,适用于双缓冲等严格配对场景,不支持多线程或单向传递。

Exchanger 是 Java 并发包中专为两个线程设计的轻量级同步工具,核心价值在于“一对一、即时交换、零拷贝”。它不靠锁、不依赖队列,也不缓存数据,而是让两个线程在 exchange() 调用点“手拉手”完成引用交换——一方交出对象,同时拿到对方的对象。这种机制天然适合双缓冲、流水线双阶段处理等严格配对协作场景。
明确适用边界:只服务成对线程
Exchanger 不是通用通信组件,它的设计前提就是“恰好两个活跃线程参与一次交换”:
- 第三个线程调用 exchange() 会无限等待,直到有另一个未配对线程出现,极易引发隐性卡死
- 若线程提前退出、未启动或中途中断,配对方将长期阻塞(除非启用超时)
- 不适合单向传递(如纯生产者→消费者)、广播通知或多线程轮换场景,此时应选 BlockingQueue 或 TransferQueue
安全初始化与类型一致保障
泛型声明必须两端统一,否则运行时可能出现 ClassCastException:
- 正确写法:Exchanger
ex = new Exchanger(); —— 两个线程都使用 byte[] 泛型 - 错误写法:一个线程用 Exchanger
,另一个用原始类型 Exchanger,编译无报错,但交换后强转失败 - 建议初始化时传非 null 哑值(如 new byte[0]),避免因 null 引发空指针且业务逻辑难追溯
带超时的 exchange 调用是生产必备
永远不要依赖无参 exchange(V x),必须使用带超时的重载防止单点故障扩散:
- 示例:byte[] other = exchanger.exchange(myBuffer, 2, TimeUnit.SECONDS);
- 超时后抛出 TimeoutException,调用方可主动释放资源、记录告警或降级处理
- 配合线程中断使用:捕获 InterruptedException 后应恢复中断状态(Thread.currentThread().interrupt();)
双缓冲实战中的典型协作模式
以图像处理流水线为例,两个线程复用两块缓冲区,通过 Exchanger 协调移交:
- 线程 A(预处理)填充 bufferA → 调用 exchanger.exchange(bufferA) 阻塞等待
- 线程 B(后处理)完成上一轮对 bufferB 的处理 → 同时调用 exchanger.exchange(bufferB)
- 交换瞬间完成:A 拿到 bufferB 开始下一轮填充,B 拿到 bufferA 开始新处理
- 优势明显:避免内存重复分配、规避读写竞争、无需额外同步语句











