CompletableFuture5-多阶段异步任务执行(多个异步任务相互依赖)

一.多阶段异步任务

在我们的实际生产过程中,可能会遇到这种场景:
   我们需要有多个异步任务,并且这些异步任务是相互依赖的,比如说,现在有三个异步任务,任务2需要使用到任务1的计算结果,任务3又需要用到任务2的计算结果,那应该如何去处理呢?使用CompletableFuture就非常简单了.

二.代码演示

1.thenApply

1.该方法可以将异步任务串行化
2.该方法对于异常的处理是:
当某一步出现异常时,直接执行异常处理和回调函数,不进行后面异步任务的处理

举例:
当没有异常时:

 ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture.supplyAsync(() -> {
            System.out.println("第一个异步任务执行完毕...");
            return 1;
        },executorService).thenApply(result -> {
            System.out.println("第二个异步任务执行完毕...");
            return result+1;
        }).thenApply(result -> {
            System.out.println("第三个异步任务执行完毕...");
            return result+1;
        }).whenComplete((result,e) -> {
            System.out.println("异步任务执行完毕,已执行回调函数.最终得结果为:"+result);
        }).exceptionally(e -> {
            e.printStackTrace();
            System.out.println(e.getCause());
            return null;
        });
        executorService.shutdown();

输出结果:
在这里插入图片描述
当出现异常时:

ExecutorService executorService = Executors.newFixedThreadPool(3);
            CompletableFuture.supplyAsync(() -> {
                System.out.println("第一个异步任务执行完毕...");
                return 1;
            },executorService).thenApply(result -> {
                //制造异常
                int i=2/0;
                System.out.println("第二个异步任务执行完毕...");
                return result+1;
            }).thenApply(result -> {
                System.out.println("第三个异步任务执行完毕...");
                return result+1;
            }).whenComplete((result,e) -> {
                System.out.println("异步任务执行完毕,已执行回调函数.最终得结果为:"+result);
            }).exceptionally(e -> {
                System.out.println("程序出现异常...");
                System.out.println(e.getCause());
                e.printStackTrace();
                return null;
            });
            executorService.shutdown();

输出结果:
在这里插入图片描述

2.handle

该方法和thenApply差不多,区别是对异常得处理
当出现异常时,可以根据所带得异常参数进行处理,后面得异步任务也可以接着执行

举例:
无异常得情况和thenApply是一样得,这里只举例有异常得情况

 ExecutorService executorService = Executors.newFixedThreadPool(3);
            CompletableFuture.supplyAsync(() -> {
                System.out.println("第一个异步任务执行完毕...");
                return 1;
            },executorService).handle((result,e) -> {
                //制造异常
                int i=2/0;
                System.out.println("第二个异步任务执行完毕...");
                return result+1;
            }).handle((result,e) -> {
                System.out.println("第三个异步任务执行完毕...");
                return result+1;
            }).whenComplete((result,e) -> {
                System.out.println("异步任务执行完毕,已执行回调函数.最终得结果为:"+result);
            }).exceptionally(e -> {
                System.out.println("程序出现异常...");
                System.out.println(e.getCause());
                e.printStackTrace();
                return null;
            });
            executorService.shutdown();

输出结果:
在这里插入图片描述
可以看到这里虽然第二个异常任务出现异常没有执行完毕,但仍然会执行第三个异步任务.

3.thenAccept.

thenAccept和thenApply也差不多,会新起一个异步任务,并且依赖前一个异步任务得结果,区别是:
thenAccept方法不需要返回值
并且因为thenAccept方法没有返回值,在使用thenAccept方法后调用回调函数时,返回得结果是null.

举例:

 ExecutorService executorService = Executors.newFixedThreadPool(3);
            CompletableFuture.supplyAsync(() -> {
                System.out.println("第一个异步任务执行完毕...");
                System.out.println("===========================================");
                return 1;
            },executorService).thenAccept((result) -> {
                System.out.println("第二个异步任务开始执行...");
                System.out.println("接收到第一个异步任务得结果:"+result);
                System.out.println("第二个异步任务执行完毕...");
                System.out.println("===========================================");
            }).whenComplete((result,e) -> {
                System.out.println("异步任务执行完毕,已执行回调函数.最终得结果为:"+result);
            }).exceptionally(e -> {
                System.out.println("程序出现异常...");
                System.out.println(e.getCause());
                e.printStackTrace();
                return null;
            });
            executorService.shutdown();

输出结果:
在这里插入图片描述

三.thenApply、handle等和对应Async方法得区别

之前说明了thenApply,handle,thenAccept方法得用法和区别,那其实这几个方法都有对应得Async方法.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
那主要得区别是什么呢?其实主要是使用线程池得区别,这里以thenApply方法进行举例说明.其他两个和这个是一样得.

1.当没有指定线程池时

thenApply和thenApplyAsync是一样得,都是使用得默认得ForkJoinPool线程池.

 CompletableFuture.supplyAsync(() -> {
                System.out.println("第一个异步任务执行完毕...使用得线程为:"+Thread.currentThread().getName());
                System.out.println("===========================================");
                return 1;
            }).thenApply((result) -> {
                System.out.println("第二个异步任务执行完毕...");
                System.out.println("使用得线程为:"+Thread.currentThread().getName());
                System.out.println("使用方法为:thenApply");
                System.out.println("===========================================");
                return result+1;
            }).thenApplyAsync(result -> {
                System.out.println("第三个异步任务执行完毕...");
                System.out.println("使用得线程为:"+Thread.currentThread().getName());
                System.out.println("使用方法为:thenApplyAsync");
                System.out.println("===========================================");
                return result+1;
            }).whenComplete((result,e) -> {
                System.out.println("所有异步任务执行完毕.");
            }).exceptionally(e -> {
                System.out.println("程序出现异常...");
                System.out.println(e.getCause());
                e.printStackTrace();
                return null;
            });

输出结果:
在这里插入图片描述

2.当使用指定线程池时

thenApply会使用指定线程池,而thenApplyAsync会使用ForkJoinPool线程池.

       ExecutorService executorService = Executors.newFixedThreadPool(3);

        CompletableFuture.supplyAsync(() -> {
            System.out.println("第一个异步任务执行完毕...使用得线程为:"+Thread.currentThread().getName());
            System.out.println("===========================================");
            return 1;
        },executorService).thenApply((result) -> {
            System.out.println("第二个异步任务执行完毕...");
            System.out.println("使用得线程为:"+Thread.currentThread().getName());
            System.out.println("使用方法为:thenApply");
            System.out.println("===========================================");
            return result+1;
        }).thenApplyAsync(result -> {
            System.out.println("第三个异步任务执行完毕...");
            System.out.println("使用得线程为:"+Thread.currentThread().getName());
            System.out.println("使用方法为:thenApplyAsync");
            System.out.println("===========================================");
            return result+1;
        }).whenComplete((result,e) -> {
            System.out.println("所有异步任务执行完毕.");
        }).exceptionally(e -> {
            System.out.println("程序出现异常...");
            System.out.println(e.getCause());
            e.printStackTrace();
            return null;
        });

        executorService.shutdown();

输出结果:
在这里插入图片描述

3.源码分析

在这里插入图片描述
在这里插入图片描述
可以看到thenApplyAsync会使用一个默认得线程池.跟着继续往下走.
在这里插入图片描述
到这里就能很清楚得了解到区别了.

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员bling

义父,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值