异步回调
异步回调、CompletableFuture、Future 与 CompletableFuture
概念
CompletableFuture 是 Callable 与 Future 的升级类
应用场景
- 并发执行任务,并需要对并发执行的全部线程进行封装,返回时
实际运用
寄快递的时候,需要同时预估不同快递的快递费用,并最后同时展示在页面上,提供给用户选择一个最便宜或者最合适的快递公司进行寄件。
解决方案
初步分析需求,只需要用 CompletableFuture.runAsync() 方法去预估,但是碰到的 问题 是,每次进行预估的时候,请求类的参数 快递类型 总是被其他的请求更改掉了。导致要么全部是申通的预估价格,要么是圆通的渠道价格。
最后解决: 采用 CompletableFuture.runAsync() 搭配 SerializationUtils.clone() 深拷贝 进行预估。成功解决问题。并且在线上的 4 核 8G 的配置下,预估 **8个 **快递公司的快递金额,可以达到 **500 毫秒 **内的请求响应速度。本地才 3 秒
/**
* 并发执行预估各个快递的价格
*
* @param jdBill 请求类
* @param user 当前用户
* @return 快递预估信息集合
*/
public List<PreOrderResult> getFastPreOrderFee(JdBill jdBill, SysUser user) {
// 初始化返回结果集合
List<PreOrderResult> objects = new ArrayList();
// 初始化线程数量
CompletableFuture[] futures = new CompletableFuture[3];
// 异步执行价格预估
futures[0] = CompletableFuture.runAsync(() -> {
// 德邦价格预估
try {
// 深拷贝请求参数类
JdBill dbBill = SerializationUtils.clone(jdBill);
PreOrderResult prePrice = this.getPrePrice(dbBill, user);
objects.add(prePrice1);
} catch (Exception e) {
e.printStackTrace();
}
}, this.threadPoolTaskExecutor);
futures[1] = CompletableFuture.runAsync(() -> {
try {
// 申通价格预估
JdBill stBill = SerializationUtils.clone(jdBill);
PreOrderResult prePrice1 = this.getPrePrice(stBill, user);
objects.add(prePrice1);
} catch (Exception e) {
e.printStackTrace();
}
}, this.threadPoolTaskExecutor);
futures[2] = CompletableFuture.runAsync(() -> {
try {
// 圆通价格预估
JdBill yundaBill = SerializationUtils.clone(jdBill);
PreOrderResult prePrice2 = this.getPrePrice(yundaBill, user);
objects.add(prePrice2);
} catch (Exception e) {
e.printStackTrace();
}
}, this.threadPoolTaskExecutor);
// 等待所有线程执行完成, 则往下继续执行
CompletableFuture.allOf(futures).join();
return objects;
}