exchanger 不保证数据安全传递,而是通过严格双线程配对和原子交换提供安全移交基础设施;数据安全取决于交换前的数据准备、所有权约定及异常兜底,需避免错配、挂起、复用、裸传null,并配合超时、中断处理与双缓冲机制。

Exchanger 本身不“保证数据安全传递”,而是通过严格的配对机制和原子交换行为,为双线程协作提供**安全移交的基础设施**。真正的数据安全,取决于你如何用它——关键不在交换动作本身,而在交换前后的数据准备、所有权约定与异常兜底。
必须严格双线程配对,避免错配或挂起
Exchanger 只认“当前到达的两个线程”,不记录身份、不缓存历史。一旦出现第三个线程调用 exchange(),它会无限等待(除非设超时),导致流程卡死;若某线程提前退出(如抛异常、return),另一方将永久阻塞。
- 确保只有且仅有两个线程使用同一个 Exchanger 实例——不要在线程池中复用
- 避免动态增减参与方,比如用固定两线程跑双缓冲流水线,而非临时启停
- 用带超时的 exchange(x, 3, TimeUnit.SECONDS) 替代无参版本,超时后主动降级或重试
交换的是引用,不是内容,需明确所有权边界
Exchanger 交换的是对象引用,不复制内容、不控制内存可见性。如果双方共用同一块 buffer,未加同步就直接读写,仍可能读到脏数据。
- 推荐配合双缓冲(如 frontBuffer / backBuffer)循环复用,交换后立即切换读写权限
- 交换前确保本方已写完数据(如 Arrays.fill(buffer, …) 完成后再调用 exchange)
- 交换后对方拿到引用,应视为“已移交所有权”,本方不得再访问该对象,直到下一轮重新获得
中断与超时必须显式处理,不能忽略
线程被中断时,exchange() 立即抛 InterruptedException,此时交换未发生,数据仍在原线程手中。若忽略该异常或不清除中断状态,协作协议会被破坏。
- 捕获 InterruptedException 后,务必调用 Thread.currentThread().interrupt() 恢复中断标志
- 超时或中断发生时,要配套清理资源:释放 buffer、关闭句柄、上报监控指标
- 不要在 exchange() 内执行耗时操作(如 IO、序列化、GC 触发),否则拖慢配对线程
类型与空值需双方约定一致
泛型保证编译期类型安全,但运行时语义需人工对齐。比如一方传 null,另一方却按非 null 解析,就会触发 NPE。
- 避免裸传 null,建议用哑值(如 new byte[0])或 Optional 封装
- 初始化阶段统一 buffer 大小与结构,确保双方对数据格式理解一致
- 在文档或注释中明确约定:谁负责填充、谁负责消费、buffer 生命周期由谁管理











