CompletableFuture异步编排

 解决问题:是在复杂的义务里面,拆分为多线程使用异步编排执行对应的业务,提高响应速度

一、创建异步对象
1.CompletableFuture 提供了四个静态方法来创建一个异步操作

runXxxx 都是没有返回结果的, supplyXxx 都是可以获取返回结果的
 
可以传入自定义的线程池,否则就用默认的线程池;
runAsync:
CompletableFuture.runAsync(()->{
            System.out.println("当前线程:"+Thread.currentThread().getId());
           int i=10/2;
            System.out.println("运行的结果"+i);
       },executor);
supplyAsync:
 CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行的结果" + i);
            return i;
        }, executor);

 
二、计算完成时回调方法

 

whenComplete 可以处理正常和异常的计算结果, exceptionally 处理异常情况。
whenComplete whenCompleteAsync 的区别:        
        whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
        whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池
来进行执行。
 * 方法完成后的感知
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程:" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("运行的结果" + i);
//            return i;
//        }, executor).whenComplete((res,excption)->{
//            //能感知异常信息,但是没法修改返回数据
//            System.out.println("异步任务成功完成了....结果是:"+res+";异常是:"+excption);
//        }).exceptionally(throwable -> {
//            //可以感知异常,同时返回默认值
//            return 10;
//        });
三、 handle 方法

complete 一样,可对结果做最后的处理(可处理异常),可改变返回值。
   /**
         * 方法完成后的处理
         */
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行的结果" + i);
            return i;
        }, executor).handle((res,exc)->{
            if(res!=null){
                return res*2;
            }
            if(exc!=null){
                return 0;
            }
            return 1;
        });
四、线程串行化方法

/**
 *线程串行化
 * 1、thenRun:不能获取到上一步的执行结果
 * 2、thenAcceptAsync能接受上一步结果,但是无返回值
 * 3、thenApplyAsync能接受上一步结果,有返回值
 */

thenRun 方法:只要上面的任务执行完成,就开始执行 thenRun ,只是处理完任务后,执行
thenRun 的后续操作
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行的结果" + i);
            return i;
        }, executor).thenRunAsync(()->{
            System.out.println("任务2启动了");
        }, executor);

thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前
任务的返回值。
  CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行的结果" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("运行的结果" + res);
            return "hello" + res;
        }, executor);

五、两任务组合 - 都要完成

 

       CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束:" );
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());

            try {
                Thread.sleep(3000);
                System.out.println("任务2结束:" );
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hellow";
        }, executor);
两个任务必须都完成,触发该任务。
 
runAfterBoth :组合两个 future ,不需要获取 future 的结果,只需两个 future 处理完任务后,
处理该任务。
  future01.runAfterBothAsync(future02,()->{
            System.out.println("任务3开始。。。。");
        },executor);

thenAcceptBoth :组合两个 future ,获取两个 future 任务的返回结果,然后处理任务,没有
返回值。
future01.thenAcceptBothAsync(future02,(f1,f2)->{
            System.out.println("任务3开始。。。。之前的结果:"+f1+"==>"+f2);
        },executor);

 
thenCombine :组合两个 future ,获取两个 future 的返回结果,并返回当前任务的返回值
   CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return f1 + ":" + f2 + "-->haha";
        }, executor);

六、两任务组合 - 一个完成

当两个任务中,任意一个 future 任务完成的时候,执行任务。

/**
 * 两个任务,只要有一个完成,我们就执行任务3
 * runAfterEitherAsync:不感知结果,自己不返回值
 * acceptEitherAsync: 感知结果,自己不返回值
 * applyToEitherAsync :感知结果,有返回值
 */
runAfterEither :两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返
回值。
  future01.runAfterEitherAsync(future02,()->{
            System.out.println("任务3开始。。");
        },executor);
acceptEither :两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
 future01.acceptEitherAsync(future02,(res)->{
            System.out.println("任务3开始。。"+res);
        },executor);
applyToEither :两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。
CompletableFuture<String> future = future01.applyToEitherAsync(future02, res -> {
            System.out.println("任务3开始。。"+res);
           return res.toString() + "_哈哈";
        }, executor);
        System.out.println("main---end"+future.get());

7 、多任务组合

 CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            return "hello.jpg";
        },executor);
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            return "黑色+256";
        },executor);
        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的介绍");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "华为";
        },executor);
allOf :等待所有任务完成
   CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureDesc, futureAttr);
        allOf.get();
        System.out.println("main---end"+futureImg.get()+"="+futureDesc.get()+"="+futureAttr.get());
anyOf :只要有一个任务完成

 CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureDesc, futureAttr);
        anyOf.get();//等待所有结果完成
        System.out.println("main---end"+anyOf.get());

 总结:异步,方法有三个特性

1、方法处理自身业务,不接受到前面传递的值,不返回值

2、方法处理自身业务,接受前面传递的值,不返回值

3、方法处理自身业务,接受前面传递的值,返回值

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

追逐路上的小人物

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值