Exchanger 不会造成传统死锁但易致单边永久阻塞,应使用带超时的 exchange(V x, long timeout, TimeUnit unit) 并捕获 TimeoutException 进行日志、告警与降级处理,确保严格双线程配对,配合中断机制和启动协调器,并在不适用场景下改用 SynchronousQueue 等替代方案。
Exchanger 本身不会造成传统意义上的死锁(即循环等待资源),但它极易引发单边永久阻塞,表现为“假死”——一个线程卡在 exchange() 上无限等待配对线程,而对方因异常、跳过、延迟或未启动根本不会来。避免这类问题,关键不是防死锁,而是防失配、保响应、控生命周期。
无参 exchange(V x) 是最大风险源,一旦配对失败就彻底挂起。应强制替换为:
exchange(V x, long timeout, TimeUnit unit) —— 超时后抛 TimeoutException,线程可及时清理、重试或降级Long.MAX_VALUE
TimeoutException 后建议记录日志、触发告警,并明确后续行为(如丢弃数据、返回默认值、关闭当前工作流)Exchanger 的设计契约是“仅且必须两个线程参与”。常见破约情形包括:
exchange() 调用exchange()
建议做法:用 CountDownLatch 或启动协调器统一控制双方进入交换点;交换逻辑封装在 try-finally 中,确保无论成功失败都完成必要清理。
立即学习“Java免费学习笔记(深入)”;
exchange() 原生响应线程中断:被中断时立即抛 InterruptedException。这为外部干预提供出口:
thread.interrupt() 主动唤醒阻塞中的线程InterruptedException 后,应恢复中断状态:Thread.currentThread().interrupt()
Thread.currentThread().isInterrupted() 并主动退出如果场景存在以下特征,Exchanger 反而增加复杂度和风险:
此时更适合换成 SynchronousQueue(支持多线程配对+超时)、TransferQueue 或基于 CompletableFuture 的异步协作模式。