CompletableFuture多任务执行及简单使用场景

目录

1.什么是CompletableFuture?

2.什么场景下使用,在项目中使用场景?

3.方法的使用详情

3.1  创建CompletableFuture对象

3.2  获取任务结果方法

3.3  异步回调处理 有参数有返回值

3.4 结果消费 有参数无返回

3.5 结果消费 无参数无返回值

3.6  异常传递 无返回值

3.7 异常传递 有返回值 跟whenComplete基本一致,区别在于handle的回调方法有返回值。

3.8.1 多任务合并thenCombine、thenAcceptBoth 和runAfterBoth

3.8.2 选择最快执行完毕的CompletableFuture,然后再选择不同的处理方式接着处理.

3.9 异常捕获

3.10 多个 CompletableFuture 组合在一起


1.什么是CompletableFuture?

先看下源码 拉到最下面 有demo 参照

 public class CompletableFuture<T> implements Future<T>, CompletionStage<T>

       简单了解下Future JDK5 新增了 Future 接口,用于描述一个异步计算的结果。 Future 的使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们的异步编程的初衷相违背,轮询的方式又会耗费无谓的 CPU 资源,而且也不能及时地得到计算结果。
  CompletionStage接口定义了任务编排的方法,执行某一阶段,可以向下执行后续阶段。(看下源码)
        所以在jdk8中引入了CompletableFuture,对Future的扩展和增强。
        也就是处理多任务的协同工作的方法。

2.什么场景下使用,在项目中使用场景?

 比如全景统计,报表分析 提高后端响应速度,方便联调测试,一个接口将数据查询出来。

3.方法的使用详情

3.1  创建CompletableFuture对象

public static CompletableFuture<Void>   runAsync(Runnable runnable);
public static CompletableFuture<Void>   runAsync(Runnable runnable, Executor executor);
public static <U> CompletableFuture<U>  supplyAsync(Supplier<U> supplier);
public static <U> CompletableFuture<U>  supplyAsync(Supplier<U> supplier, Executor executor);

3.2  获取任务结果方法

// 如果完成则返回结果,否则就抛出具体的异常
public T get() throws InterruptedException, ExecutionException 
 
// 最大时间等待返回结果,否则就抛出具体异常
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
 
// 完成时返回结果值,否则抛出unchecked异常。为了更好地符合通用函数形式的使用,如果完成此 CompletableFuture所涉及的计算引发异常,则此方法将引发unchecked异常并将底层异常作为其原因 不会强制开发者抛出。get()方法抛出的是经过检查的异常,ExecutionException, InterruptedException 需要用户手动处理(抛出或者 try catch)
public T join()
 
// 如果完成则返回结果值(或抛出任何遇到的异常),否则返回给定的 valueIfAbsent。
public T getNow(T valueIfAbsent)
 
// 如果任务没有完成,返回的值设置为给定值
public boolean complete(T value)
 
// 如果任务没有完成,就抛出给定异常
public boolean completeExceptionally(Throwable ex) 

3.3  异步回调处理 有参数有返回值

        thenApply和thenApplyAsync区别在于,使用thenApply方法时子任务与父任务使用的是同一个线程,而thenApplyAsync在子任务中是另起一个线程执行任务,并且thenApplyAsync可以自定义线程池,默认的使用ForkJoinPool.commonPool()线程池。

public <U> CompletableFuture<U>  thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U>  thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U>  thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)

3.4 结果消费 有参数无返回

thenAccept在上一个任务执行结束后,将上一个任务返回结果作为入参,但无返回

public CompletableFuture<Void>  thenAccept(Consumer<? super T> action),
public CompletableFuture<Void>  thenAcceptAsync(Consumer<? super T> action),
public CompletableFuture<Void>  thenAcceptAsync(Consumer<? super T> action,Executor executor)

3.5 结果消费 无参数无返回值

会在上一个任务执行结束后才开始处理,既没有入参也没有返回值
public CompletableFuture<Void> thenRun(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action)
public CompletableFuture<Void> thenRunAsync(Runnable action,Executor executor)

3.6  异常传递 无返回值

        whenComplete是当某个任务执行完成后执行的回调方法,会将执行结果或者执行期间抛出的异常传递给回调方法,如果是正常执行则异常为null,回调方法对应的CompletableFuture的result和该任务一致,如果该任务正常执行,则get方法返回执行结果,如果是执行异常,则get方法抛出异常。

public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {return uniWhenCompleteStage(null, action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor)

3.7 异常传递 有返回值 跟whenComplete基本一致,区别在于handle的回调方法有返回值。

 

public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn),
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn),
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)

3.8.1 多任务合并thenCombine、thenAcceptBoth 和runAfterBoth

这三个方法都是将两个CompletableFuture组合起来处理,只有两个任务都正常完成时,才进行下阶段任务。

三种方法也含有thenCombineAsync、 thenAcceptBothAsync、 runAfterBothAsync方法 也可指定自定义线程池

区别:thenCombine会将两个任务的执行结果作为所提供函数的参数,且该方法有返回值;thenAcceptBoth同样将两个任务的执行结果作为方法入参,但是无返回值;runAfterBoth没有入参,也没有返回值

public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor);

3.8.2 选择最快执行完毕的CompletableFuture,然后再选择不同的处理方式接着处理.

区别:applyToEither有参数有返回值 acceptEither,runAfterEither无返回值 ; runAfterEither无参数 三个方法 带有异步执行 也可定义线程池

  这种组合模式只要有一个异步任务成功,就会触发后续的方法,比如我们组合任务1和任务2,如果任务1执行完成就直接执行任务3,无视任务2。反之任务2先完成直接执行任务3,无视任务1。

public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn);
public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action);
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action); 
  
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action,Executor executor);

3.9 异常捕获

        任务1执行过程中可能报错,我们希望能够从逻辑的角度处理掉,那么我们就可以在任务1后面接一个exceptionally方法,然后再接上任务2。这样一来,任务1执行报错就会走到exceptionally,反之就会走到任务2的代码段

 

public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn)

3.10 多个 CompletableFuture 组合在一起

     allof多个任务都执行完成后才会执行,只有有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。

      anyof是多个任务只要有一个任务执行完成,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回执行完成任务的结果。

 

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) 
  CompletableFuture是多个任务都执行完成后才会执行,只有有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)  
  CompletableFuture是多个任务只要有一个任务执行完成,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回执行完成任务的结果。

依赖关系

依赖关系
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的完成

demo 方便了解及使用

public class demo01 {

  /**
   * 创建对象返回结果
   * @throws ExecutionException
   * @throws InterruptedException
   */
  @Test
  public void demo01() throws ExecutionException, InterruptedException{
    CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
      System.out.println("do something....");
      return "result";
    });
    //等待任务执行完成
    System.out.println("结果->" + cf.get());

  }

  /**
   * 创建对象指定线程池
   * @throws ExecutionException
   * @throws InterruptedException
   */
  @Test
  public void demo02() throws ExecutionException, InterruptedException{
    // 自定义线程池
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    CompletableFuture<List<String>> cf = CompletableFuture.supplyAsync(() -> {
      System.out.println("do something222....");
      return Arrays.asList("result");
    }, executorService);

    //等待子任务执行完成
    System.out.println("结果->" + cf.get());
  }

  /**
   * 获取结果
   * @throws InterruptedException
   * @throws ExecutionException
   * @throws TimeoutException
   */
  @Test
  public void demo03() throws InterruptedException, ExecutionException, TimeoutException {
    // 自定义线程池
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    CompletableFuture<List<String>> cf = CompletableFuture.supplyAsync(() -> {
      System.out.println("do something333....");
      try {
        Thread.sleep(3000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      return Arrays.asList("result");
    }, executorService);


    //等待子任务执行完成
    System.out.println("结果->" + cf.get(1000, TimeUnit.MILLISECONDS));
//    System.out.println("结果->" + cf.join());
  }


  /**
   * 异步回调处理  thenApply和thenApplyAsync
   *
   *
   * Thread[ForkJoinPool.commonPool-worker-3,5,main] cf1 do something....
   * Thread[ForkJoinPool.commonPool-worker-5,5,main] cf2 do something....
   * cf1结果->1
   * cf2结果->3
   */
  @Test
  public void demo04(){
    CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
      System.out.println(Thread.currentThread() + " cf1 do something....");
      return 1;
    });

    CompletableFuture<Integer> cf2 = cf1.thenApply((result) -> {
      System.out.println(Thread.currentThread() + " cf2 do something....");
      result += 2;
      return result;
    });
    //等待任务1执行完成
    System.out.println("cf1结果->" + cf1.join());
    //等待任务2执行完成
    System.out.println("cf2结果->" + cf2.join());

    CompletableFuture<String> stringCompletableFuture = cf1.thenApply((result) -> {
      int p = 1/0;
      return result + "第一次 + ";
    }).thenApply((result) -> {
      return result + "第二次";
    });

    System.out.println("合在一起结果->" + stringCompletableFuture.join());
  }


  /**
   * 异步回调处理  thenApply和thenApplyAsync
   * 有参数 有返回值
   */
  @Test
  public void demo05(){
    CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
      System.out.println(Thread.currentThread() + " cf1 do something....");
      return 1;
    });

    CompletableFuture<Integer> cf2 = cf1.thenApplyAsync((result) -> {
      System.out.println(Thread.currentThread() + " cf2 do something....");
      result += 2;
      return result;
    });
    //等待任务1执行完成
    System.out.println("cf1结果->" + cf1.join());
    //等待任务2执行完成
    System.out.println("cf2结果->" + cf2.join());
  }



  /**
   * 结果消费
   * thenAccept和thenAcceptAsync
   * 有参数 无返回值
   */
  @Test
  public void demo06(){
    CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
      return "初始结果";
    });
    cf1.thenAccept((result) -> {
      String finalresult = "最终结果 ---" + result;
      System.out.println("两次结果->" + finalresult);
    });
  }

  /**
   * 结果消费
   * thenRun和thenRunAsync
   * 无参数 无返回值
   */
  @Test
  public void demo07(){
    CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
      return "初始结果";
    });
    CompletableFuture<Void> thenRun = cf1.thenRun(() -> {
      System.out.println("do something ....");
    });

    System.out.println("cf1结果->" + cf1.join());
    System.out.println("thenRun结果->" + thenRun.join());
  }

  /**
   * 结果消费
   * whenComplete和whenCompleteAsync
   * 无参数 无返回值
   */
  @Test
  public void demo08() {
    CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
      int p = 1 / 0;
      return "初始结果";
    });
    CompletableFuture<String> cf2 = cf1.whenComplete((result, e) -> {
      System.out.println("上个任务结果:" + result);
      System.out.println("上个任务抛出异常:" + e);
      System.out.println(Thread.currentThread() + " cf2 do something....");
    });

  }
    /**
     * 结果消费
     * handle和handleAsync
     * 无参数 无返回值
     */
    @Test
    public void demo09(){
      CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
//        int p = 1/0;
        return "初始结果";
      });
      CompletableFuture<String> cf2 = cf1.handle((result, e) -> {
        System.out.println("上个任务结果:" + result);
        System.out.println("上个任务抛出异常:" + e);
        String finalResult = result + "-- 最终结果";
        return finalResult;
      });
      System.out.println("最终结果:" + cf2.join());
  }


  /**
   * 组合
   *
   *
   * cf1 执行结果->73
   * cf2 执行结果->85
   * thenCombine返回结果 ->158
   * thenAcceptBoth 返回结果7385
   * thenAcceptBoth 返回结果null
   * runAfterBoth do something....
   * runAfterBoth 返回结果null
   */
  @Test
  public void demo10(){
    CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
      int result1 = RandomUtil.randomInt(10, 100);
      System.out.println("cf1 执行结果->" + result1);
//      int p =1/0;
      return result1;
    });
    CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(() -> {
      int result2 = RandomUtil.randomInt(10, 100);
      System.out.println("cf2 执行结果->" + result2);
      return result2;
    });
    CompletableFuture<Integer> cf9 = CompletableFuture.supplyAsync(() -> {
      int result3 = RandomUtil.randomInt(10, 100);
      System.out.println("cf9 执行结果->" + result3);
      return result3;
    });

    CompletableFuture<Integer> cf3 = cf1.thenCombine(cf2, (result1, result2) -> {
      return result1 + result2;
    });
    System.out.println("thenCombine返回结果 ->" + cf3.join());



    CompletableFuture<Void> voidCompletableFuture = cf1.thenAcceptBoth(cf2, (result1, result2) -> {
      System.out.println("thenAcceptBoth 返回结果->" + result1 + result2);
    });
    System.out.println("thenAcceptBoth 返回结果->" + voidCompletableFuture.join());


    CompletableFuture<Void> runAfterBoth = cf1.runAfterBoth(cf2, () -> {
      System.out.println("runAfterBoth do something....");
    });
    System.out.println("runAfterBoth 返回结果->" + runAfterBoth.join());

  }


  /**
   * 异常捕获
   */
  @Test
  public void demo11(){
    CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
        int p = 1/0;
      return "初始结果";
    }).exceptionally(e -> {
      System.out.println("xxx接口查询数据异常" + e.getMessage());
      return null;
    });
  }

  /**
   * 组合
   */
  @Test
  public void demo12() {
    HashMap<String, Object> map = new HashMap<>(2);

    CompletableFuture<HashMap<String, Object>> jigouanjianzongshu = CompletableFuture.supplyAsync(() -> {
      System.out.println("各机构案件总数当前线程:" + Thread.currentThread().getId());
      try {
        Thread.sleep(5000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      map.put("各机构案件总数", "jigouanjianzongshu");
      return map;
    }).exceptionally(e -> {
      System.out.println("各机构案件总数执行有误");
      return null;
    });


    CompletableFuture<HashMap<String, Object>> shuziheji = CompletableFuture.supplyAsync(() -> {
      System.out.println("数字合计当前线程:" + Thread.currentThread().getId());
//      int p = 1/0;
      map.put("数字合计", "shuziheji");
      return map;
    }).exceptionally(e -> {
      System.out.println("数字合计查询执行有误");
      return null;
    });

    CompletableFuture<Void> allCombindFuture = CompletableFuture.allOf(jigouanjianzongshu, shuziheji);
    System.out.println("执行结果" + allCombindFuture.join());

//    CompletableFuture<Object> objectCompletableFuture = CompletableFuture.anyOf(jigouanjianzongshu, shuziheji);
//    System.out.println("执行结果" + objectCompletableFuture.join());
    System.out.println(map);
  }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值