exchanger 是 java 并发包中用于双向同步交换数据的阻塞式协作工具,基于 locksupport.park()/unpark() 实现配对等待,需成对调用并推荐使用带超时的 exchange() 以避免无限阻塞。

Exchanger 是 Java 并发包(java.util.concurrent)中用于**双向同步交换数据**的工具类。它不处理“等待阻塞”的逻辑,而是**主动设计为阻塞式协作机制**:当两个线程调用 exchange(V x) 时,若只有一个线程到达,它就会阻塞等待另一个线程到来;只有双方都到达后,才完成数据交换并各自返回。
Exchanger 的阻塞本质是配对等待
Exchanger 内部维护一个“配对槽位”,每次 exchange() 调用都会尝试与另一个未匹配的线程配对:
- 第一个调用线程进入等待状态(挂起),直到第二个线程也调用
exchange() - 第二个线程到达时,唤醒第一个线程,双方交换数据,然后同时返回
- 如果超时参数被使用(
exchange(V x, long timeout, TimeUnit unit)),等待线程会在超时后抛出TimeoutException,不再阻塞
阻塞发生在用户线程调用点,不是后台线程管理
Exchanger 不启动任何后台线程,也不使用锁或条件队列模拟等待——它的阻塞基于 LockSupport.park()/unpark() 实现:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 线程在配对失败时调用
LockSupport.park()进入 WAITING 状态 - 配对成功时,由对方线程调用
LockSupport.unpark()唤醒 - 这种机制轻量、无竞争、不消耗 CPU,且能响应中断(被中断时抛出
InterruptedException)
实际使用中要注意的等待行为
看似简单的交换,容易因线程生命周期或异常导致单边等待:
- 若一个线程提前退出(如抛异常、return、被 interrupt),另一方会一直阻塞,直到超时或被中断
- 建议始终使用带超时的
exchange(),避免无限等待 - 确保成对调用:每个
exchange()都应有且仅有一个对应方,不能重复调用同一 Exchanger 实例而忽略配对关系 - 例如:生产者-消费者场景中,若生产者崩溃,消费者可能卡在
exchange()上,需靠超时+重试或关闭机制兜底
中断和超时是控制阻塞的关键手段
Exchanger 尊重线程中断语义,也支持显式超时:
- 调用线程被中断 → 立即抛出
InterruptedException,退出阻塞 - 使用
exchange(x, 5, TimeUnit.SECONDS)→ 最多等 5 秒,超时抛TimeoutException - 两者可共存:超时时间内若被中断,优先响应中断
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










