exchanger的核心是exchange()方法,实现两线程原子交换引用:无参版严格配对阻塞,推荐用带超时版防级联阻塞;类型安全与空值需手动保障;不支持多线程配对,无内部状态,实例可复用。

Exchanger 的核心方法是 exchange(),它让两个线程在同步点“面对面交货”——同时阻塞、原子交换、零拷贝传递对象引用。
exchange(V x):成对阻塞,严格配对
调用该方法的线程会立即进入 WAITING 状态,不消耗 CPU,也不自旋。它不会继续执行,直到另一个线程也调用同一 Exchanger 实例的 exchange()。二者不是“先来后到”,而是“必须齐到才触发”。一旦配对成功,双方在一次原子操作中互换引用:线程 A 传入的对象交给线程 B,线程 B 的对象交给线程 A。返回值永远是对方的数据,不是自己原来的。
exchange(V x, long timeout, TimeUnit unit):生产环境唯一推荐用法
无参版本在实际系统中极易引发级联阻塞,因此必须使用带超时的重载:
- 超时后抛出 TimeoutException,当前线程可捕获并执行降级逻辑(如记录告警、释放资源、切换备用缓冲区)
- 超时只影响当前线程,另一方若后续到达仍会完成交换,但结果无人接收
- 建议按任务类型设合理阈值:I/O 类设 2–5 秒,纯计算类可缩至 100–500 毫秒
类型安全与空值控制需由使用者保障
Exchanger 本身不校验泛型一致性或 null 值,但错误会直接导致运行时异常:
- 两端必须使用相同泛型声明,例如
Exchanger<byte></byte>,否则可能触发 ClassCastException - 允许传 null,但极易引发下游 NPE;建议初始化时用哑值(如
new byte[0])或业务层提前判空 - 交换的是引用,不是副本——这对大数组(
byte[]、int[])意义重大,避免内存拷贝开销
不支持多线程,也不维护状态
Exchanger 不是队列,没有内部缓冲,也不缓存历史数据:
- 第三个线程调用会无限等待,直到有第四个线程出现配对,逻辑完全不可控
- 每次 exchange 都是一次独立事件,无需 reset 或 cleanup,实例可复用
- 不保证公平性(默认构造),启用公平模式(
new Exchanger(true))会降低吞吐约 10%–20%
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











