CompletableFuture 异步编排

CompletableFuture简介

CompletableFuture执行

  • CompletableFuture 提供了四个静态方法来创建一个异步操作。runAsync()方法不支持返回值,使用supplyAsync()方法可以获取到返回值,
  • 通过指定Executor 来指定线程池来执行异步代码,所有没有显式Executor参数的异步方法都使用ForkJoinPool.commonPool() (除非它不支持至少两个并行级别,在这种情况下,会创建一个新线程来运行每个任务)。

runAsync不支持返回值

public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) 

supplyAsync支持返回值

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) 
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

【注意】:默认的commonPool的这些线程都是守护线程。我们在编程的时候需要谨慎使用守护线程,如果将我们普通的用户线程设置成守护线程,当我们的程序主线程结束,JVM中不存在其余用户线程,那么CompletableFuture的守护线程会直接退出,造成任务无法完成的问题!!

代码示例:

private static void syncExecute() throws ExecutionException, InterruptedException{
   CompletableFuture<String> t1Future = CompletableFuture.supplyAsync( () -> {

      System.out.println( "t1Future 执行中。。。。" );
      return "t1Future 执行了";
   } );

   String t1 = t1Future.get();
   System.out.println(t1);
}

CompletableFuture任务执行过程中,出现异常会导致任务中断,因此要对异常进行捕获。

CompletableFuture执行结果

1. get()和join()

作用: 都是用来获取CompletableFuture异步执行结果。

区别:

  1. join()方法抛出的是uncheck异常(即RuntimeException),不会强制开发者抛出,
  2. get()方法抛出的是经过检查的异常,ExecutionException, InterruptedException 需要用户手动处理(抛出或者 try catch)

2. whenComplete & whenCompleteAsync

  • 将CompletableFuture任务的执行结果及异常信息,作为参数传递到whenComplete函数中。
  • CompletableFuture任务执行完成时,执行给定的操作,不论任务是否出现异常,都会调用whenComplete函数。
  • whenComplete函数执行完成后,会返回任务执行结果。如果whenComplete出现异常,任务执行将会中断,因此,要对异常进行捕获,并抛出。
//当前线程继续执行
public CompletionStage<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);
//提交线程池执行(默认线程池)  
public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
//指定线程池(指定的Executor)
public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor);            

区别:

  1. whenComplete:是执行当前任务的线程继续执行whenComplete任务
  2. whenCompleteAsync:是把whenCompleteAsync这个任务提交给线程池来执行

3.exceptionally

  • 返回一个新的CompletableFuture,当前面的CompletableFuture完成时,它也完成,当它异常完成时,给定函数的异常触发这个CompletableFuture的完成。
  • 任务出现异常时,会优先执行该方法。

代码示例:

private static void exceptionallyTest() throws ExecutionException, InterruptedException{

   CompletableFuture<String> t1Future = CompletableFuture.supplyAsync( () -> {
      try{
         Thread.sleep( 50 );
      }
      catch( InterruptedException e ){
         e.printStackTrace();
      }
      System.out.println( "t1Future 执行中。。。。" );
      int a = 10 / 0;
      return "t1Future 执行了";
   } );

   t1Future.whenComplete( new BiConsumer<String, Throwable>(){

      @Override
      public void accept( String s, Throwable throwable ){

         System.out.println( "t1Future执行完成 值:" + s + ",whenComplete执行中。。" );
      }
   } );
   t1Future.exceptionally( new Function<Throwable, String>(){

      @Override
      public String apply( Throwable throwable ){

         System.out.println( "t1Future执行异常,exceptionally执行中。。" );
         return "exceptionally";
      }
   } );
   t1Future.get();
}

执行结果:

t1Future 执行中。。。。
t1Future执行异常,exceptionally执行中。。
t1Future执行完成 值:null,whenComplete执行中。。

多任务组合

并行执行

  • allOf (与)当所有给定的 CompletableFuture 完成时,返回一个新的 CompletableFuture。
  • anyOf (或)当任何一个给定的CompletablFuture完成时,返回一个新的CompletableFuture。
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)

1. allOf

等待所有给定任务执行完成后,才会继续执行。

private static void multiTask() throws ExecutionException, InterruptedException{

   CompletableFuture<String> t1Future = CompletableFuture.supplyAsync( () -> {
      System.out.println( "t1Future 执行中。。。。" );
      return "t1Future 执行了";
   } );

   CompletableFuture<String> t2Future = CompletableFuture.supplyAsync( () -> {
      System.out.println( "t2Future 执行中。。。。" );
      return "t2Future 执行了";
   } );

   CompletableFuture<String> t3Future = CompletableFuture.supplyAsync( () -> {
      System.out.println( "t3Future 执行中。。。。" );
      return "t3Future 执行了";
   } );

   CompletableFuture[] completableFutures = new CompletableFuture[]{ t1Future, t2Future, t3Future };

   //所有任务执行完成后
   CompletableFuture.allOf( completableFutures ).whenComplete( ( v, t ) -> {
      for( CompletableFuture completableFuture : completableFutures ){
         try{
            System.out.println( completableFuture.get());
         }
         catch( Exception e ){
            e.printStackTrace();
         }
      }

   } ).get();

   System.out.println( "所有任务全部执行完成。。。。" );
}

2.anyOf

只要给定的任务中,有一个执行完成就会继续执行,用于多条件只要满足一个就行继续的场景

CompletableFuture[] completableFutures = new CompletableFuture[]{ t1Future, t2Future, t3Future };

CompletableFuture.anyOf( completableFutures ).whenComplete( ( v, t ) -> {
   System.out.println("whenComplete 执行中。。。。  ");
} ).get();
System.out.println( "所有任务全部执行完成。。。。" );

执行结果

t1Future 执行中。。。。
whenComplete 执行中。。。。  
所有任务全部执行完成。。。。

串行执行

  • thenApply():把前面任务的执行结果,交给后面的Function
  • thenCompose():用来连接两个有依赖关系的任务,结果由第二个任务返回

thenApply 和 thenCompose的区别:

  1. thenApply转换的是泛型中的类型,返回的是同一个CompletableFuture;
  2. thenCompose将内部的CompletableFuture调用展开来并使用上一个CompletableFutre调用的结果在下一步的CompletableFuture调用中进行运算,是生成一个新的CompletableFuture。

3.thenApply()

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

代码示例

CompletableFuture<Integer> t1Future = CompletableFuture.supplyAsync( () -> {
   int result = 10;
   System.out.println( "t1Future 执行中。。。。" );
   return result;
} ).thenApply( new Function<Integer, Integer>(){

   @Override
   public Integer apply( Integer s ){
      return s * 2;
   }
} );
//简写
CompletableFuture<Integer> t2Future = CompletableFuture.supplyAsync( () -> {
   int result = 10;
   System.out.println( "t1Future 执行中。。。。" );
   return result;
} ).thenApply( item -> {
   return item * 3;
} );

System.out.println( t1Future.get() );
System.out.println( t2Future.get() );

and集合关系

  • thenCombine():合并任务,有返回值
  • thenAccepetBoth():两个任务执行完成后,将结果交给thenAccepetBoth处理,无返回值
  • runAfterBoth():两个任务都执行完成后,执行下一步操作(Runnable类型任务)

4.thenCombine()

合并任务,并将任务结果作为所提供函数的参数,返回一个新的CompletionStage

public <U,V> CompletionStage<V> thenCombine (CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);
//使用默认线程池,异步执行
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);
//指定线程池,异步执行
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor);

代码示例

private static void test2() throws ExecutionException, InterruptedException{

   CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync( () -> {
      int result = 10;
      return result;
   } );

   CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync( () -> {
      int result = 20;
      return result;
   } );

   CompletableFuture<Integer> resultFuture = future1.thenCombine( future2, new BiFunction<Integer, Integer, Integer>(){

      @Override
      public Integer apply( Integer integer, Integer integer2 ){

         Integer result = integer + integer2;
         return result;
      }
   } );
   System.out.println( "resultFuture=" + resultFuture.get() );

}

4.thenAccepetBoth()

当此阶段和另一个给定阶段都正常完成时,将使用两个结果作为所提供操作的参数来执行该阶段,无返回值。

public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);

public <U> CompletionStage<Void> thenAcceptBothAsync (CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);

public <U> CompletionStage<Void> thenAcceptBothAsync (CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action,Executor executor);

代码示例

CompletableFuture<Void> resultFuture = future1.thenAcceptBoth( future2, new BiConsumer<Integer, Integer>(){

   @Override
   public void accept( Integer integer, Integer integer2 ){

      int result = integer + integer2;
      System.out.println( "执行结果:" + result );
   }
} );

or聚合关系

  • applyToEither():两个任务哪个执行的快,就使用哪一个结果,有返回值
  • acceptEither():两个任务哪个执行的快,就消费哪一个结果,无返回值
  • runAfterEither():任意一个任务执行完成,进行下一步操作(Runnable类型任务)

5.applyToEither()

当此阶段或其他给定阶段正常完成时,该阶段将以相应的结果作为所提供函数的参数执行。有返回值。哪个执行的快,就使用哪一个结果,有返回值。

public <U> CompletionStage<U> applyToEither (CompletionStage<? extends T> other,Function<? super T, U> fn);

public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn);

public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn, Executor executor);

代码示例

CompletableFuture<Integer> resultFuture = future1.applyToEither( future2, new Function<Integer, Integer>(){

   @Override
   public Integer apply( Integer integer ){
      System.out.println("执行结果:"+integer);
      return integer;
   }
} );

6.acceptEither()

两个任务哪个执行的快,就消费哪一个结果,无返回值
当此阶段或其他给定阶段正常完成时,该阶段将以相应的结果作为所提供操作的参数执行。

public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action);
     
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);
     
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action, Executor executor);

代码示例

CompletableFuture resultFuture = future1.acceptEither( future2, new Consumer<Integer>(){

   @Override
   public void accept( Integer integer ){

      System.out.println( "执行结果:" + integer );
   }
} );

resultFuture.get();

7.runAfterEither()

任意一个任务执行完成,进行下一步操作(Runnable类型任务)

public CompletionStage<Void> runAfterEither(CompletionStage<?> other, Runnable action);

public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action);

public CompletionStage<Void> runAfterEitherAsync (CompletionStage<?> other, Runnable action,  Executor executor);

代码示例

CompletableFuture resultFuture = future1.runAfterEither( future2, new Runnable(){

   @Override
   public void run(){
      System.out.println("执行runnable......");
   }
} );
resultFuture.get();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值