• 第二部分:并发工具类24->CompletableFuture,异步编程没那么难


    1.异步编程

    串行操作并行化,涉及到异步化

    异步化,是并行方案得以实施的接触,利用多线程优化性能这个核心方案来实施的基础。

    jdk1.8提供了CompletableFuture支持异步编程

    2.CompletableFuture 核心优势

    烧水泡茶,3个任务
    任务1,洗水壶,烧开水
    任务2,洗茶壶,洗茶杯,拿茶叶
    任务3,泡茶

    任务3需要等待任务1,和任务2都完成才可以执行

    image

    有一些没有见过的方法,
    runAsync()
    supplyAsync()
    thenCombine()

    特点:
    1.无需手工维护线程,没有手工维护线程的工作,给任务分配线程不需要我们关注
    2.语意清晰,f3 = f1.thenCombine(f2,() -> {})能够清晰表述“任务3等待任务1和任务2都完成后才开始”
    3.代码简练,专注业务逻辑

    
    //任务1:洗水壶->烧开水
    CompletableFuture<Void> f1 = 
      CompletableFuture.runAsync(()->{
      System.out.println("T1:洗水壶...");
      sleep(1, TimeUnit.SECONDS);
    
      System.out.println("T1:烧开水...");
      sleep(15, TimeUnit.SECONDS);
    });
    //任务2:洗茶壶->洗茶杯->拿茶叶
    CompletableFuture<String> f2 = 
      CompletableFuture.supplyAsync(()->{
      System.out.println("T2:洗茶壶...");
      sleep(1, TimeUnit.SECONDS);
    
      System.out.println("T2:洗茶杯...");
      sleep(2, TimeUnit.SECONDS);
    
      System.out.println("T2:拿茶叶...");
      sleep(1, TimeUnit.SECONDS);
      return "龙井";
    });
    //任务3:任务1和任务2完成后执行:泡茶
    CompletableFuture<String> f3 = 
      f1.thenCombine(f2, (__, tf)->{
        System.out.println("T1:拿到茶叶:" + tf);
        System.out.println("T1:泡茶...");
        return "上茶:" + tf;
      });
    //等待任务3执行结果
    System.out.println(f3.join());
    
    void sleep(int t, TimeUnit u) {
      try {
        u.sleep(t);
      }catch(InterruptedException e){}
    }
    // 一次执行结果:
    T1:洗水壶...
    T2:洗茶壶...
    T1:烧开水...
    T2:洗茶杯...
    T2:拿茶叶...
    T1:拿到茶叶:龙井
    T1:泡茶...
    上茶:龙井
    

    3.CompletableFuture对象

    创建

    //使用默认线程池
    static CompletableFuture<Void> 
      runAsync(Runnable runnable)
    static <U> CompletableFuture<U> 
      supplyAsync(Supplier<U> supplier)
    //可以指定线程池  
    static CompletableFuture<Void> 
      runAsync(Runnable runnable, Executor executor)
    static <U> CompletableFuture<U> 
      supplyAsync(Supplier<U> supplier, Executor executor)  
    

    runAsync(Runnable runnable)
    supplyAsync(Supplier supplier)

    区别是什么?Runnable接口的run方法没有返回值,Supplier的get方法是有返回值的,其余额外的是带线程池传递
    默认不传的话用的是默认ForkJoinPool线程池,线程数默认是cpu核数
    建议根据不同业务类型创建不同的线程池,以免相互干扰

    注意事项:
    创建完CompletableFuture对象之后,自动异步执行runnable.run()方法或者supplier.get()方法

    这也可以通过future来获取执行结果和判断线程是否执行结束。

    4.CompletableFuture的高级功能

    CompletableFuture类实现了CompletionStage接口,有40多个方法

    CompletionStage接口

    大概说明:
    串行关系

    并行关系
    image
    汇聚关系
    image
    异常处理

    前面提到的f3 = f1.thenCombine(f2, () -> {})描述的就是汇聚关系,说白了就是AND聚合关系
    f3是等f1,f2都执行完,才执行;当然还是or关系,只有其中1个执行完就可以执行

    4.1 串行关系

    thenApply,thenAccept,thenRun,thenCompose四个接口

    
    CompletionStage<R> thenApply(fn);
    CompletionStage<R> thenApplyAsync(fn);
    CompletionStage<Void> thenAccept(consumer);
    CompletionStage<Void> thenAcceptAsync(consumer);
    CompletionStage<Void> thenRun(action);
    CompletionStage<Void> thenRunAsync(action);
    CompletionStage<R> thenCompose(fn);
    CompletionStage<R> thenComposeAsync(fn);
    

    4.2 and 汇聚关系

    CompletionStage applyToEither(other, fn);
    CompletionStage applyToEitherAsync(other, fn);
    CompletionStage acceptEither(other, consumer);
    CompletionStage acceptEitherAsync(other, consumer);
    CompletionStage runAfterEither(other, action);
    CompletionStage runAfterEitherAsync(other, action);
    
    CompletionStage<R> thenCombine(other, fn);
    CompletionStage<R> thenCombineAsync(other, fn);
    CompletionStage<Void> thenAcceptBoth(other, consumer);
    CompletionStage<Void> thenAcceptBothAsync(other, consumer);
    CompletionStage<Void> runAfterBoth(other, action);
    CompletionStage<Void> runAfterBothAsync(other, action);
    

    4.3 or汇聚关系

    
    CompletionStage applyToEither(other, fn);
    CompletionStage applyToEitherAsync(other, fn);
    CompletionStage acceptEither(other, consumer);
    CompletionStage acceptEitherAsync(other, consumer);
    CompletionStage runAfterEither(other, action);
    CompletionStage runAfterEitherAsync(other, action);
    

    4.4 异常处理

    
    CompletableFuture<Integer> 
      f0 = CompletableFuture.
        .supplyAsync(()->(7/0))
        .thenApply(r->r*10);
    System.out.println(f0.join());
    

    正常是try-catch,函数式编程中,更简单,提供了链式处理异常

    
    CompletionStage exceptionally(fn);
    CompletionStage<R> whenComplete(consumer);
    CompletionStage<R> whenCompleteAsync(consumer);
    CompletionStage<R> handle(fn);
    CompletionStage<R> handleAsync(fn);
    

    异常范例

    CompletableFuture f0 = CompletableFuture .supplyAsync(()->(7/0)) .thenApply(r->r*10) .exceptionally(e->0);System.out.println(f0.join());
    
    原创:做时间的朋友
  • 相关阅读:
    字符串练习
    Python基础
    熟悉常见的Linux命令
    大数据概述
    实验三 递归下降分析法
    简化C语言文法
    实验一 词法分析程序实验
    词法分析程序
    制作首页的显示列表
    完成登录功能
  • 原文地址:https://www.cnblogs.com/PythonOrg/p/14987204.html
Copyright © 2020-2023  润新知