• CompletableFuture的使用


    CompletableFuture是对Future的扩展和增强。CompletableFuture实现了Future接口,并在此基础上进行了丰富的扩展,完美弥补了Future的局限性,同时CompletableFuture实现了对任务编排的能力。借助这项能力,可以轻松地组织不同任务的运行顺序、规则以及方式。从某种程度上说,这项能力是它的核心能力。而在以往,虽然通过CountDownLatch等工具类也可以实现任务的编排,但需要复杂的逻辑处理,不仅耗费精力且难以维护。

    依赖关系
    thenApply():把前面任务的执行结果,交给后面的Function
    thenCompose():用来连接两个有依赖关系的任务,结果由第二个任务返回
    and集合关系
    thenCombine():合并任务,有返回值
    thenAccepetBoth():两个任务执行完成后,将结果交给thenAccepetBoth处理,无返回值
    runAfterBoth():两个任务都执行完成后,执行下一步操作(Runnable类型任务)
    or聚合关系
    applyToEither():两个任务哪个执行的快,就使用哪一个结果,有返回值
    acceptEither():两个任务哪个执行的快,就消费哪一个结果,无返回值
    runAfterEither():任意一个任务执行完成,进行下一步操作(Runnable类型任务)
    并行执行
    allOf():当所有给定的 CompletableFuture 完成时,返回一个新的 CompletableFuture
    anyOf():当任何一个给定的CompletablFuture完成时,返回一个新的CompletableFuture
    结果处理
    whenComplete:当任务完成时,将使用结果(或 null)和此阶段的异常(或 null如果没有)执行给定操作
    exceptionally:返回一个新的CompletableFuture,当前面的CompletableFuture完成时,它也完成,当它异常完成时,给定函数的异常触发这个CompletableFuture的完成

    CompletableFuture–小窍门
    1.所有的thenXXX都只能处理正确结果。Whencomplete和handler可以处理正确和错误的结果。
    2.如果方法名中有accept,那末表示只能接受结果,不能返回新的结果
    3.如果方法名中有apply,那么表示可以返回新的结果
    4.如果方法名中有run,表示既不能接收结果,也不能返回结果。只在合适的时机被触发。
    一些练习:

    package com.one;
    
    import java.util.concurrent.CompletableFuture;
    
    /**
     * <p>文件名称:TestCompeleteFuture</p>
     * <p>文件描述:TODO</p>
     * <p>公司名称:安徽皖通邮电股份有限公司 </p>
     * <p>完成日期:2022年07年05日 08:55:26</p>
     * author 王韵通
     */
    public class TestCompeleteFuture {
        public static void main(String[] args) {
            CompletableFuture<String> future=new CompletableFuture<>();
            future.complete("OK");
            //所有以thenXXX开头的方法都用于处理正确结果
            //因为第一级的回调没有返回结果,所以第二级回调收到的参数是null
            future.thenAccept(result-> System.out.println(result))//ok
                    .thenAccept(result-> System.out.println(result));//null
    
            future.thenApply(result->{
                System.out.println(result);
                return "Processed";//第一级的回调中返回了新的结果
            }).thenAccept(result->{
                System.out.println(result);
            });
                future.thenCompose(result->{
                    //返回一个新的CompletableFuture
                    return CompletableFuture.completedFuture(result+100);
                }).thenAccept(System.out::println);
    
                future.thenApply(result->{
                    return result+100;
                }).thenAccept(System.out::println);
    
                //thenApply中是以同步的方式返回新的结果;而thenCompose
            //是以异步的方式返回新的结果
            CompletableFuture<Integer> future1 = new CompletableFuture<>();
            CompletableFuture<Integer> future2 = new CompletableFuture<>();
            future1.complete(10);
            future2.complete(20);
            /**
             * 将两个future合并,当他们都执行完毕后触发互调
             * 再回调中返回一个新的结果
             */
            future1.thenCombine(future2,(result1,result2)->result1+result2)
                    .thenAccept(System.out::println);
            /**
             *
             */
            future1
                    .thenAcceptBoth(future2,(r1,r2)-> System.out.println(r1*r2))
                    .thenAccept(System.out::println);//输出null
            CompletableFuture<Integer> future3 = new CompletableFuture<>();
            future3.complete(20);
    
            future3.whenComplete((result,number)->{
                if(number!=null){
                    System.out.println(result);
                }else{
                    System.out.println("buxing");
                }
    
            });
            //默认情况下,回调方法和future.complete()是在同一个线程中运行
            CompletableFuture<String> f = new CompletableFuture<>();
            f.thenApply(result->{
                System.out.println("L2"+Thread.currentThread());
                return result;
            }).thenAcceptAsync(r->{
                System.out.println("L3"+Thread.currentThread());
            });
            System.out.println("L1"+Thread.currentThread());
            f.complete("");
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
  • 相关阅读:
    git学习笔记——分支、commit版本切换篇
    使用EasyPlayer播放H.265视频流
    【Java八股文总结】之数据结构
    《学术小白学习之路14》主题建模——主题概率分布相似度计算
    LeetCode 160. 相交链表
    弘辽科技:拼多多怎么可以引来自然流量?怎么得自然流量?
    C++学习day--22 宏和结构体
    算法题笔记 6-10 (青蛙跳台阶)
    再聊Java Stream的一些实战技能与注意点
    Linux 线程互斥
  • 原文地址:https://blog.csdn.net/weixin_44569326/article/details/125614238