交换器Exchanger
About 1 min
线程之间的协作姿势千姿百态,如果两个线程之间的数据想要互换这该如何实现?对头,Exchanger
就是为此而生的。它可以在两个线程之间交换数据,而且只能是2
个线程,线程多了还不行。今天我们就通过实例来学习一下Exchanger
的用法。
使用
Exchanger
是在两个任务之间交换对象的栅栏,当任务进入栅栏时,它们各自拥有一个对象。当他们离开时,它们都拥有之前由对方线程持有的对象。
分析
下面我们举个例子:两个人完成一笔交易,一手交钱,一手交货
public class ExchangerTest {
final static Exchanger<String> exchanger = new Exchanger<>();
public static void main(String[] args) {
var executor = Executors.newCachedThreadPool();
executor.execute(() -> doExchangeWork("金钱"));
executor.execute(() -> doExchangeWork("货物"));
executor.shutdown();
}
private static void doExchangeWork(String product) {
try {
System.out.println(Thread.currentThread().getName() + " 正在把 " + product + " 给出去, time: " + LocalDateTime.now());
Thread.sleep(new Random().nextInt(1000));
var receivedData = exchanger.exchange(product);
System.out.println(Thread.currentThread().getName() + " 得到 " + receivedData + ", time: " + LocalDateTime.now());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出结果:
pool-1-thread-1 正在把 金钱 给出去, time: 2023-08-16T21:16:30.403456
pool-1-thread-2 正在把 货物 给出去, time: 2023-08-16T21:16:30.403454
pool-1-thread-1 得到 货物, time: 2023-08-16T21:16:30.952205
pool-1-thread-2 得到 金钱, time: 2023-08-16T21:16:30.952462
当线程1
调用Exchange对象的exchange()
方法后,它会进入阻塞状态直到线程2
也调用了exchange()
方法,然后两线程以安全的方式交换彼此的数据,之后线程1
和2
继续运行。