异步编排 CompletableFuture 的学习

当我们有如下场景:
在这里插入图片描述
以上要么去数据库中查询,要么就远程调用查询,所花费的时间都不一样,那么我们很容易想到使用多线程来解决该问题,但是如果有各种麻烦的顺序(比如5要在1、2后执行,6要在2、3后执行),我们这时使用多线程就会比较复杂。
那么现在有个类CompletableFuture 来封装了这种复杂性:

CompletableFuture

对于CompletableFuture类的每一个方法,都有提供线程池和不提供线程池两种方法,如果不提供线程池就会使用它自定义的线程池。我们这里使用我们提供的线程池。

runAsync() 和 supplyAsync()

CompletableFuture有几个基本的方法: runAsyncsupplyAsync ,看下面的例子就懂了区别:

ExecutorService executorService = Executors.newFixedThreadPool(10);

CompletableFuture<Void> async = CompletableFuture.runAsync(() -> {
            System.out.println("当前正在执行");
        }, executorService);
CompletableFuture<String> async1 = CompletableFuture.supplyAsync(() -> {
            return "返回值";
        }, executorService);
        System.out.println(async1.get());

可以发现,runAsync()是没有返回值的,supplyAsync()是有返回值的,通过返回的CompletableFuture类调用get()方法得到具体的返回值

线程完成后的处理

主要的方法有handle()exceptionally(), 第一个方法可以拿到返回值和异常,第二个方法只能拿到异常。

   CompletableFuture.supplyAsync(()->{
            return "hello";
        },executorService).handle((t,u)->{
            return "结果是"+t+","+"异常有:"+u ;
        })
        .exceptionally(e->{
            System.out.println();
            return "异常处理后的返回值";
        });

串行化

thenRunAsync()

该方法只能串行化的执行,第二个线程不能接收到第一个线程的任何信息

CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> {
            return "返回值";
        }, executorService).thenRunAsync(() -> {
            System.out.println("");
        });
thenAcceptAsync()

该方法可以拿到第一个线程的返回值:

CompletableFuture.supplyAsync(()->{
            return "hello";
        }).thenAcceptAsync(r->{
            System.out.println("前一个线程的返回值是"+r);
        },executorService);

thenApplyAsync

该方法不仅可以拿到前一个线程的返回值,也可以自己返回值:

CompletableFuture.supplyAsync(()->{
            return "hello";
        }).thenApplyAsync(r->{
            return "new"+r;
        },executorService);

带顺序的异步处理:

现在就来解决我们最开始提出的问题:

ExecutorService executorService = Executors.newFixedThreadPool(10);

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品属性信息");
            return "iphone";
        }, executorService);

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品图片");
            return "http://aaa.jpg";
        }, executorService);

CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品介绍");
            return "Iphone 13";
        }, executorService);

如上,现在有三个任务是异步执行的,那么我们需要第5个任务是1和2之后执行,6要在2、3后执行,那么就使用allof()方法

  CompletableFuture<String> future5 = CompletableFuture.allOf(future1, future2).thenApplyAsync((r) -> {
            return "第五个任务执行完毕";
        }, executorService);
        System.out.println(future5.get());
        CompletableFuture<String> future6 = CompletableFuture.allOf(future2, future3).thenApplyAsync((r) -> {
            return "第六个任务执行完毕";
        }, executorService);
        System.out.println(future6.get());

当我们执行future5.get()和 future6.get()的方法时,future5会阻塞等待1和2 的完成,future6会阻塞等待2和3的完成,

除了allof()方法外,还有一个 anyof()方法,就是等待其中之一的线程执行完毕之后就执行后面的线程

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值