两个线程在栅栏处相遇,交换数据后各自离开,就像物物交换市场!
一、Exchanger是什么?
核心概念
Exchanger<V> exchanger = new Exchanger<>();
// 线程A
String dataA = "来自A的数据";
String dataFromB = exchanger.exchange(dataA); // 阻塞,等待B
// 线程B
String dataB = "来自B的数据";
String dataFromA = exchanger.exchange(dataB); // 阻塞,等待A
生活类比:
Exchanger像快递代收点📦:
- 你把包裹放在代收点
- 等对方也放一个包裹
- 双方交换后各自取走
二、基本使用
public class ExchangerDemo {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();
// 线程1:生产者
new Thread(() -> {
try {
String data = "生产的数据";
System.out.println("线程1准备数据: " + data);
String received = exchanger.exchange(data);
System.out.println("线程1收到: " + received);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 线程2:消费者
new Thread(() -> {
try {
Thread.sleep(1000); // 模拟处理延迟
String data = "处理结果";
System.out.println("线程2准备数据: " + data);
String received = exchanger.exchange(data);
System.out.println("线程2收到: " + received);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
输出:
线程1准备数据: 生产的数据
线程2准备数据: 处理结果
线程1收到: 处理结果
线程2收到: 生产的数据
三、实战场景
场景1:遗传算法
public class GeneticAlgorithm {
private final Exchanger<List<Gene>> exchanger = new Exchanger<>();
public void run() {
// 线程1:种群A进化
new Thread(() -> {
List<Gene> populationA = initPopulation();
for (int gen = 0; gen < 100; gen++) {
evolve(populationA);
// 每10代交换基因
if (gen % 10 == 0) {
populationA = exchanger.exchange(populationA);
}
}
}).start();
// 线程2:种群B进化
new Thread(() -> {
List<Gene> populationB = initPopulation();
for (int gen = 0; gen < 100; gen++) {
evolve(populationB);
if (gen % 10 == 0) {
populationB = exchanger.exchange(populationB);
}
}
}).start();
}
}
场景2:数据校对
public class DataValidator {
private final Exchanger<DataBatch> exchanger = new Exchanger<>();
// 线程1:从数据库读取
public void readFromDB() {
DataBatch dbData = queryDatabase();
DataBatch fileData = exchanger.exchange(dbData);
// 比对数据
compare(dbData, fileData);
}
// 线程2:从文件读取
public void readFromFile() {
DataBatch fileData = parseFile();
DataBatch dbData = exchanger.exchange(fileData);
// 比对数据
compare(fileData, dbData);
}
}
四、超时机制
try {
// 等待5秒
String data = exchanger.exchange("数据", 5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
System.out.println("等待超时,对方未到达");
}
五、面试要点💯
Q: Exchanger适用场景?
A:
- 遗传算法(基因交换)
- 数据校对(两份数据比对)
- 管道设计(生产-消费配对)
Q: Exchanger和BlockingQueue的区别?
A:
- Exchanger:双向交换,必须成对
- BlockingQueue:单向传递,生产者→队列→消费者
下一篇→ 优雅关闭线程池的艺术🛑