背景
最近在学习雷丰阳老师的JUC教程,正好学到了completableFuture这个知识点,上班的时候有一个需求需要我在服务添加一个接口,该接口需要返回4个数据,而这四个数据正好分别是从四个第三方接口获取汇总而成的。正好可以实践一下。
为什么是CompletableFuture?
如果按照正常的模式,我们需要串行去请求4个第三方接口,会导致响应时间的线性叠加。
所以需要异步去请求而且是要拿到结果并汇总。这时候我们会想到Future。
那为什么不用Future呢?因为Future.get()是阻塞的。这时候你又会说了可以用FutureTask.isDone()轮询来优化。
这时候我就会问你,那如果有多个异步任务要组合,异步回调的场景呢?
CompletableFuture实现了Future接口,也就是说Future有的功能,CompleteFuture也有,CompleteFuture还有更多对异步任务组合回调的任务以及它还有future.get(2L,TimeUnit.SECONDS)获取结果,但只等待指定的时间功能。
public class CompletableFuture<T> implements Future<T>, CompletionStage<T>
实践
在实际的工作中,我分别对四个第三方接口执行有返回值的异步任务supplyAsync,并使用allOf(XX).whenComplete来对四个第三方接口都完成时做汇总。
XX是四个异步Future
优化
如果要对四个第三方接口返回的信息优化成可配模式,那么XX内容就是动态的。而且allOf方法是只要XX其中一个接口报错,汇总都是为空。我们要确保即使有一个第三方接口出错也要给接口返回默认值,以及汇总都有数据。
这时候需要建一个新类,用来存储future以及默认值
@Data
public class FutureTask {
private JSONObject errMsg;
private CompletableFuture<JSONObject> future;
public FutureTask(JSONObject errMsg, CompletableFuture<JSONObject> future) {
this.errMsg = errMsg;
this.future = future;
}
}
List<FutureTask> tasks = Lists.newArrayListWithExpectedSize(4);
//设置为可配
if (!Objects.isNull(null) && needEpidemic) {
CompletableFuture<JSONObject> epidemicFuture = CompletableFuture.supplyAsync(() -> {
// 处理流调数据
return handleEpidemic(param, new JSONObject());
});
//可配添加到task里,并设置默认返回值
tasks.add(new FutureTask(new JSONObject().fluentPut("epidemic", "2"), epidemicFuture)
);}
因为我们知道allOf只要一个由错误会导致全军覆没,所以我们在外层捕获异常并忽略,里层捕获异常并设置默认值。
学习其他功能
推荐这篇文章,我也跟着他的例子,敲了一遍其他功能
大致功能图