该篇文章,就是给大家带来基于@Async的使用,再结合 CompletableFuture 去实现我们刚提到的场景。
事不宜迟,进入主题。
正文
结合实例,给大家去讲解,介绍@Async的使用,再结合 CompletableFuture 的使用。
需求场景:
拉取第三方数据 ,分别需要拉取 A业务数据(需要2秒) 、拉取 B业务数据(需要2秒)、拉取 C业务数据(需要2秒) ,最后再一并返回给前端。
还涉及到了 超时调用的问题(项目要求每个接口不能超过 5秒 ),这时候就特别需要注意多线程的使用了。
这种情形,我们就会想到使用 异步:
写过模拟的测试接口:
运行结果我们看一下:
因为异步标记了三个方法,所以看到主线程时间没被受影响,但是同时返回值也拿不到。
这样 耗时接近0秒, 但是返回给前端的数据就是 null了。
当前的执行简图:
OK,就是基于当前这个情况,我们开始加入 CompletableFuture 的使用 。
对代码进行改造一下:
调用模拟接口代码也需要跟着调整:
运行结果:
当前的执行简图:
为什么耗时是2秒,帮助理解:
CompletableFuture.allOf(a,b,c).join(); 我们这里 allOf 传递了 三个 异步线程的返回值, 所以看到上图,也就出现了三个等待返回值的坑位 A B C。可以把这个想象成一辆车,三个位, 必须人满才发车。
那么要等多久呢?
这三个人几乎是同时走向这辆车的,但是无论其他人走多快,因为得整整齐齐,所以耗时取决于这三个坑位,最慢上车的那个人。
再次验证:
直接把pullDataA 改为等待8秒 ,
运行结果:
耗时 8秒
额外啰唆一下:
看到这,各位看官应该是都掌握怎么去使用操作 CompletableFuture 了。
只要我想要某个异步线程的返回值,我就把这个方法返回接收值CompletableFuture 加入到 allOf 里面去 。
对,这么使用确实是ok的。
其实,只要你使用到了 返回接收值CompletableFuture ,其实就已经开始触发,并不是一定要用allOf。
举例说明:
ps:那么我们怎么去使用这个CompletableFuture ,大家应该多少会玩了吧。
再啰唆一下,
其实我的这个打印输出,
System.out.println(a.get()+b.get()+c.get());
里面也调用了get() ,也就是也算是使用了。
那么再举一个小例子:
这种情况,我们使用了 CompletableFuture<String>分别去接收返回值,但是我们后面没去使用操作它们,也没使用allOf , 看下运行结果:
也就是说,这种情况,不会因为 我们使用了 CompletableFuture 而促使让主线程去等待任何异步线程。
OK,该篇就到这吧。