Exchanger:线程间的数据交换站🔄

44 阅读2分钟

两个线程在栅栏处相遇,交换数据后各自离开,就像物物交换市场!

一、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:单向传递,生产者→队列→消费者

下一篇→ 优雅关闭线程池的艺术🛑