【Java异步编程】CompletableFuture综合实战:泡茶喝水与复杂的异步调用
文章目录
- 一. 两个异步任务的合并:泡茶喝水
- 二. 复杂的异步调用:结果依赖,以及异步执行调用等
一. 两个异步任务的合并:泡茶喝水
下面的代码中我们实现泡茶喝水。这里分3个任务:任务1负责洗水壶、烧开水,任务2负责洗茶壶、洗茶杯和拿茶叶,任务3负责泡茶。其中任务3要等待任务1和任务2都完成后才能开始。
public class DrinkTea {
private static final int SLEEP_GAP = 3;//等待3秒
public static void main(String[] args) {
// 异步任务1
CompletableFuture<Boolean> washJob = CompletableFuture.supplyAsync(() ->
{
Print.tcfo("洗茶杯");
//线程睡眠一段时间,代表清洗中
sleepSeconds(SLEEP_GAP);
Print.tcfo("洗完了");
return true;
});
// 异步任务2
CompletableFuture<Boolean> hotJob = CompletableFuture.supplyAsync(() ->
{
Print.tcfo("洗好水壶");
Print.tcfo("烧开水");
//线程睡眠一段时间,代表烧水中
sleepSeconds(SLEEP_GAP);
Print.tcfo("水开了");
return true;
});
// 等待任务1,2执行完成后,任务3执行thenCombine
CompletableFuture<String> drinkJob =
//hotOk、washOK,指的是两个异步任务的返回结果
washJob.thenCombine(hotJob, (hotOk, washOK) ->
{
if (hotOk && washOK) {
Print.tcfo("泡茶喝,茶喝完");
return "茶喝完了";
}
return "没有喝到茶";
});
// 阻塞主线程:等待任务 3 执行结果
Print.tco(drinkJob.join());
}
执行日志:
[ForkJoinPool.commonPool-worker-9|DrinkTea.lambda$main$0]:洗茶杯
[ForkJoinPool.commonPool-worker-2|DrinkTea.lambda$main$1]:洗好水壶
[ForkJoinPool.commonPool-worker-2|DrinkTea.lambda$main$1]:烧开水
[ForkJoinPool.commonPool-worker-9|DrinkTea.lambda$main$0]:洗完了
[ForkJoinPool.commonPool-worker-2|DrinkTea.lambda$main$1]:水开了
[ForkJoinPool.commonPool-worker-9|DrinkTea.lambda$main$2]:泡茶喝,茶喝完
[main]:茶喝完了
JVM退出钩子(定时和顺序任务线程池) starting....
JVM退出钩子(定时和顺序任务线程池) 耗时(ms): 1
通过整体的执行过程可以发现:
- 给任务分配线程的工作由线程池自动完成。
- 任务之间的依赖关系一目了然。以下面的伪代码为例:
job3 = job1.thenCombine( job2, (result1, result2)->{回调逻辑})
等待任务1,2执行完成后,任务3执行thenCombine,其中result1、result2是任务1、任务2的返回值。基于两个异步任务的返回值判断是否进行泡茶喝。
- join: 阻塞主线程:等待任务 3 执行结果
参考:《Java高并发核心编程》-尼恩
二. 复杂的异步调用:结果依赖,以及异步执行调用等
具体代码查看gitee提交:[并发编程]CompletableFuture实现复杂的异步调用:结果依赖,以及异步执行调用等
具体实现了:
- 通过策略模式,实现了流程下各个执行逻辑
- 通过使用CompletableFuture实现各执行逻辑异步执行
- 通过使用thenRunAsync等待前面步骤执行,进而实现5,6步的异步执行,加快执行速度
- 使用CompletableFuture.allOf(step5, step6),合并5,6步的结果。