交换者 Exchanger
1. 前言
本节带领大家认识第五个常用的 Java 并发工具类之 Exchanger。
本节先介绍 Exchanger 工具类表达的概念和最基本用法,接着通过一个生活中的例子为大家解释 Exchanger 工具类的使用场合,然后通过简单的编码实现此场景,最后带领大家熟悉 Exchanger 工具类的其他重要方法。
下面我们正式开始介绍吧。
2. 概念解释
Exchanger 表示 “交换者”,此工具类提供了两个线程在某个时间点彼此交换信息的功能。使用 Exchanger 的重点是成对的线程使用 exchange () 方法,当一对线程都到达了同步点时,彼此会进行信息交换。我们通过一张图可直观了解其逻辑。
概念已经了解了,Exchanger 工具类最基本的用法是怎样的呢?看下面。
3. 基本用法
// 创建一个 Exchanger 对象
Exchanger exchanger = new Exchanger();
// 线程1开始处理逻辑
...
// 线程1将自己的信息交换给线程2,并一直等待线程2的交换动作
exchanger.exchange("待交换信息");
// 线程1等到了线程2的交换结果后继续处理后继逻辑
...
// 线程2开始处理逻辑
...
// 线程2将自己的信息交换给线程2,并一直等待线程1的交换动作
exchanger.exchange("待交换信息");
// 线程2等到了线程1的交换结果后继续处理后继逻辑
...
是不是很简单,那 Exchanger 应用在哪些场合比较合适呢?下面我们给出最常用的场景说明。
4. 常用场景
Exchanger 工具类提供了成对的线程彼此同步数据的场合。我们举一个生活中的例子说明:快递员为客户派送物品,客户要求订单采用货到付款的方式进行支付。当快递员送货上门后,出示收款二维码(或者 POM 刷卡支付),客户当面扫码(或刷卡)支付。在这个例子中,快递员交换出去的是货物收到的是款项,而客户正好相反。我们用 Exchanger 工具类简单实现这个场景,请看下面代码。
5. 场景案例
import java.util.Random;
import java.util.concurrent.Exchanger;
public class ExchangerTest {
// 创建一个 Exchanger 对象
private static Exchanger<Object> exchanger = new Exchanger();
public static void main(String[] args) throws InterruptedException {
// 模拟快递员
new Thread(() -> {
System.out.println( Thread.currentThread().getName() + "送货上门中...");
// 模拟快递送货用时
try {
Thread.sleep(new Random().nextInt(10000));
} catch (Exception e) {}
System.out.println( Thread.currentThread().getName() + "货物已经送到,等待客户付款");
// 进行货款交换
try {
Object money = exchanger.exchange("快递件");
// 收到货款
System.out.println("已经收到货款" + money + ",继续下一单派送...");
} catch (Exception e) {}
}, "快递员").start();
// 模拟客户
new Thread(() -> {
System.out.println( Thread.currentThread().getName() + "工作中...");
// 模拟工作中用时
try {
Thread.sleep(new Random().nextInt(10000));
} catch (Exception e) {}
System.out.println( Thread.currentThread().getName() + "接到快递员取件电话,货物已经送到");
try {
// 进行货款交换
Object packagz = exchanger.exchange("1000元");
// 收到货款
System.out.println("已经收到货物" + packagz + "...");
} catch (Exception e) {}
}, "客户").start();
}
}
运行上面代码,我们观察一下运行结果。
快递员送货上门中...
客户工作中...
快递员货物已经送到,等待客户付款
客户接到快递员取件电话,货物已经送到
已经收到货物快递件...
已经收到货款1000元,继续下一单派送...
观察结果,和我们的预期一致。
6. 其他方法介绍
Exchanger 工具类的用法比较简单,其提供了两个 exchange 方法,除过上面代码中使用的方法之外,其还对进行了重载。
exchange (V, timeout, TimeUnit) 方法。
允许设置交换等待的超时时间,当时间过后还未交换到需要的对方数据,则不再等待,继续后继逻辑执行。
7. 小结
本节通过一个简单的例子,介绍了 Exchanger 的使用场景和基本用法。希望大家在学习过程中,多思考勤练习,早日掌握之。