Exchanger的核心作用是让两个线程在汇合点阻塞等待并安全交换对象引用,适用于双缓冲处理、批量数据交接等严格配对场景;必须恰好两个线程参与,推荐使用带超时的exchange方法以防死锁。

Exchanger 的核心作用与适用场景
Exchanger 是一个用于两个线程之间**成对同步交换数据**的并发工具类。它不是用来传递消息或共享状态,而是让两个线程在某个“汇合点”彼此等待,并安全地交换各自持有的对象引用。典型场景包括:双缓冲数据处理(如一个线程填充缓冲区A,另一个线程消费缓冲区B,然后双方交换)、生产者-消费者协作中批量数据交接、或者需要严格配对协作的并行计算任务。
基本使用方式:调用 exchange() 方法
每个线程调用 exchanger.exchange(data) 时会阻塞,直到另一个线程也调用该方法。一旦两个线程都到达,它们交换各自传入的对象,并同时返回对方的数据。注意:必须恰好两个线程参与;第三个线程调用会一直等待,除非有超时机制。
- 无参
exchange(V x):无限等待配对线程 - 带超时的
exchange(V x, long timeout, TimeUnit unit):避免死锁,推荐在生产环境使用 - 若等待超时,抛出
TimeoutException;若被中断,抛出InterruptedException
一个可运行的双缓冲交换示例
以下代码模拟两个线程交替填充与处理缓冲区:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
<p>public class ExchangerExample {
static class Producer implements Runnable {
private final Exchanger<int> exchanger;
private int[] buffer = new int[10];</int></p><pre class="brush:php;toolbar:false;"> Producer(Exchanger<int> ex) { this.exchanger = ex; }
@Override
public void run() {
try {
for (int i = 0; i exchanger;
private int[] buffer = new int[10];
Consumer(Exchanger<int> ex) { this.exchanger = ex; }
@Override
public void run() {
try {
for (int i = 0; i ex = new Exchanger();
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(new Producer(ex));
pool.submit(new Consumer(ex));
pool.shutdown();
}</int></int>}
关键注意事项与最佳实践
Exchanger 不是通用通信机制,使用时需特别注意:
- 只支持严格两个线程配对,不适用于多线程广播或轮询场景
- 交换的是对象引用,不是深拷贝;若双方后续修改同一数组/集合,需自行保证线程安全
- 建议始终配合超时使用,防止因某一线程异常退出导致另一方永久挂起
- 可重复使用,每次
exchange()都是一次独立配对;无需重置或重建实例 - 内部基于 AQS 实现,性能高效,无明显锁开销
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










