CompletableFuture 异步编排
阿昌 Java小菜鸡

阿昌总结今天学习到的CompletableFuture

当我们在异步任务编程的时候,可能会有场景如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1LdHaaAS-1634223766164)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014221550374.png)]

可能你会想到用之前我们学到的Callable的方式去获取结果后,再执行;

但是这样子不能保证是异步与异步之间的结果;

C不能感知到AB的结果后再异步执行;

所以,这里我们就引出了 ==CompletableFuture==

一、前言

什么是CompletableFuture呢?

CompletableFuture 和 FutureTask 同属于 Future 接口的实现类,都可以获取线程的执行结果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nvaoL5aY-1634223766166)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014221836628.png)]


二、API

方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)

1、是否有返回值

()->{}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YYXjP8gp-1634223766168)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014222101147.png)]

1
CompletableFuture future = CompletableFuture.XXXAsync(()->{});
  • runXxxx 都是没有返回结果

  • supplyXxx 都是可以获取返回结果

  • 可以传入自定义的线程池,否则就用默认的线程池;


2、是否有回调方法,不能改变返回值

(t,error)->{}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gaYsfAPn-1634223766170)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014222323835.png)]

只能返回结果,不能改变返回值

whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。

  • whenComplete 和 whenCompleteAsync 的区别
    • whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
    • whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池
      来进行执行。

3、有回调方法,能改变返回值

(t,error)->{return xx;}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-428fVOoD-1634223766173)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014222901876.png)]

只能返回结果,能改变返回值

和 complete 一样,可对结果做最后的处理(可处理异常),可改变返回值。


4、线程串行化方法

T:上一个任务返回结果的类型

U:当前任务的返回值类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qlkCCQCb-1634223766175)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014223120068.png)]

  • **thenApply(resp->{return xx;})**:
    • 当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值。
  • **thenAccept(resp->{})**:
    • 消费处理结果。接收任务的处理结果,并消费处理,无返回结果。
  • **thenRun(()->{})**:
    • 只要上面的任务执行完成,就开始执行 thenRun,只是处理完任务后,执行thenRun 的后续操作

带有 Async 默认是异步执行的。同之前

  • 以上都要前置任务成功完成。

5、两任务组合—都要完成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t3HmgRoQ-1634223766177)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014224101520.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VejFV16m-1634223766179)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014224107385.png)]

两个任务必须都完成,触发该任务。

下面的CompletableFuture为另一个任务

  • **thenCombine(CompletableFuture,(r1,r2)->{return xx;},线程池)**:

    • 组合两个 future,获取两个 future 的返回结果,并返回当前任务的返回值
    1
    future01.thenCombineAsync(future02,(r1,r2)-{return xx;},excutor);
  • **thenAcceptBoth(CompletableFuture,(r1,r2)->{},线程池)**:

    • 组合两个 future,获取两个 future 任务的返回结果,然后处理任务,没有返回值。
    1
    future01.thenAcceptBothAsync(future02,(f1,f2)->{},executor);
  • **runAfterBoth(CompletableFuture,()->{},线程池)**:

    • 组合两个 future,不需要获取 future 的结果,只需两个 future 处理完任务后,处理该任务。
    1
    future01.runAfterBothAsync(future02,()->{},executor);

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8GzY58ZY-1634223766181)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014224726858.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HdzZQMq4-1634223766182)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014224733317.png)]

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

下面的CompletableFuture为另一个任务

  • **applyToEither(CompletableFuture,res->{return xxx;},线程池)**:

    • 两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。
    1
    future01.applyToEitherAsync(future02,res->{},executor);
  • **acceptEither(CompletableFuture,res->{},线程池)**:res为两个任务中执行完成的那个的返回值

    • 两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
    1
    future01.acceptEitherAsync(future02,res->{},executor);
  • **runAfterEither(CompletableFuture,()->{},线程池)**:

    • 两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返回值。
    1
    future01.runAfterEitherAsync(future02,()->{},executor);

7、 多任务组合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o7bjfkEk-1634223766184)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014225313597.png)]

  • allOf

    • 等待所有任务完成

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PJvp4p74-1634223766185)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014225355717.png)]

  • anyOf

    • 只要有一个任务完成

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BmjTBpfK-1634223766186)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211014225419071.png)]

 请作者喝咖啡