CompletableFuture实践

407 阅读2分钟

背景

最近在学习雷丰阳老师的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只要一个由错误会导致全军覆没,所以我们在外层捕获异常并忽略,里层捕获异常并设置默认值。

学习其他功能

推荐这篇文章,我也跟着他的例子,敲了一遍其他功能

juejin.cn/post/697055…

大致功能图