CompletableFuture的API使用详解

本文深入探讨了Java中的CompletableFuture,包括如何创建、获取结果、设置回调、异常处理、任务合并等。讲解了thenRun、thenAccept、thenApply的用法,以及exceptionally和handle异常处理策略。此外,还介绍了如何使用allOf()和anyOf()合并多个任务,并展示了complete和completeExceptionally方法的使用场景。
摘要由CSDN通过智能技术生成

1. 创建CompletableFuture对象

CompletableFuture提供了四个静态方法用来创建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)
  • runAsync 方法接收的是 Runnable 的实例,意味着它没有返回值
  • supplyAsync 方法对应的是有返回值的情况
  • 这两个方法的带 executor 的变种,表示让任务在指定的线程池中执行,不指定的话,通常任务是在 ForkJoinPool.commonPool() 线程池中执行的。

2. 返回结果获取

以下4个方法用于获取结果

//同步获取结果
public T    get()
public T    get(long timeout, TimeUnit unit)
public T    getNow(T valueIfAbsent)
public T    join()

获取结果时,会阻塞。
getNow有点特殊,如果结果已经计算完则返回结果或者抛出异常,否则返回给定的valueIfAbsent值。
join()与get()区别在于join()返回计算的结果或者抛出一个unchecked异常(CompletionException),而get()返回一个具体的异常.

3.计算结果完成后的回调方法

public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)

上面4个方法是当计算阶段结束的时候触发。可以看到Action的类型是BiConsumer<? super T,? super Throwable>它可以处理正常的计算结果,或者异常情况。BiConsumer有两个入参,分别代表计算返回值,另外一个是异常。

whenComplete 和 whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行,也就是可能是其他线程来执行。

示例

public static void whenComplete() throws Exception {
   
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
   
        try {
   
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
   
        }
        if(new Random().nextInt()%2>=0) {
   
            int i = 12/0;
        }
        System.out.println("run end ...");
    });
    
    future.whenComplete(new BiConsumer<Void, Throwable>() {
   
        @Override
        public void accept(Void t, Throwable action) {
   
            System.out.println("执行完成!");
        }
        
    });
    //以下是lamda表达式的写法
    /*
	future.whenComplete((v,e)->{
       System.out.println("执行完成!");
    });
    */
    future.exceptionally(new Function<Throwable, Void>() {
   
        @Override
        public Void apply(Throwable t) {
   
            System.out.println("执行失败!"+t.getMessage());
            return null;
        }
    });
    
    TimeUnit.SECONDS.sleep(2);
}

4.让线程串行执行的三个方法thenRun、thenAccept、thenApply

当计算结算完成之后,后面可以接继续一系列的thenXX,来完成值的转化或下一步执行.

  • thenRun:前一个线程执行完后执行thenRun,不需要依赖前一个线程的结果并且没有返回值
  • thenAccept:前一个线程执行完后执行thenAccept,需要依赖前一个线程的结果,但是没有返回值
  • thenApply:前一个线程执行完后执行thenApply,需要依赖前一个线程的结果,并有返回值

源码方法定义

thenRun

public CompletableFuture<Void> thenRun(Runnable action);
public CompletableFuture<Void> thenRunAsync(Runnable action);
public CompletableFuture<Void> thenRunAsync(Runnable action,Executor executor) ;

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)

T:为上一个线程执行的结果类型

thenApply

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)

T:上一个任务返回结果的类型
U:当前任务的返回值类型

示例

CompletableFuture.runAsync(() -> {
   }).thenRun(() 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值