CompletableFuture类提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法。

总结

分类 方法名 描述
创建异步任务 runAsync 不支持返回值
supplyAsync 支持返回值
创建异步任务 thenRunthenRunAsync 不接参数、无返回值
thenAcceptthenAcceptAsync 接返回值、无返回值
thenApplythenApplyAsync 接返回值、有返回值
exceptionallyexceptionallyAsync 接异常、有返回值
whenCompletewhenCompleteAsync 接返回值和异常、无返回值
handlehandleAsync 接返回值和异常、有返回值
两个任务组合 thenComposethenComposeAsync 任务转化
thenCombinethenCombineAsync “且”组合、接返回值、有返回值
thenAcceptBoththenAcceptBothAsync “且”组合、接返回值、无返回值
runAfterBothrunAfterBothAsync “且”组合、不接参数、无返回值
applyToEitherapplyToEitherAsync “或”组合、接返回值、有返回值
acceptEitheracceptEitherAsync “或”组合、接返回值、无返回值
runAfterEitherrunAfterEitherAsync “或”组合、不接参数、无返回值
多个任务组合 anyOf “任意一个”组合
allOf “所有”组合

在CompletableFuture中如果使用没有指定线程池的方法,则会使用ForkJoinPool.commonPool()作为它的线程池执行异步代码。

创建异步任务

不支持返回值

  • 方法签名
    1
    2
    3
    4
    // 使用默认线程池中的线程
    public static CompletableFuture<Void> runAsync(Runnable runnable);
    // 使用自定义线程池中的线程
    public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);
  • 示例代码
    1
    2
    3
    CompletableFuture.runAsync(() -> {
    // TODO 执行任务
    });

支持返回值

  • 方法签名

    1
    2
    3
    4
    // 使用默认线程池中的线程
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
    // 使用自定义线程池中的线程
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
  • 示例代码

    1
    2
    3
    4
    CompletableFuture.supplyAsync(() -> {
    // TODO 执行任务
    return null;
    });

任务完成时回调方法

当CompletableFuture任务执行完成或者抛出异常的时候,可以执行特定的回调方法。

不接参数、无返回值

前一个任务执行完成后执行;任务之间无参数传递,回调方法无返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    public CompletableFuture<Void> thenRun(Runnable action);
    // 使用默认线程池中的线程
    public CompletableFuture<Void> thenRunAsync(Runnable action);
    // 使用自定义线程池中的线程
    public CompletableFuture<Void> thenRunAsync(Runnable action, Executor executor);
  • 示例代码
    1
    2
    3
    4
    CompletableFuture.runAsync(() -> {
    }).thenRun(() -> {
    // TODO 执行任务
    });

接返回值、无返回值

前一个任务执行完成后执行;前一个任务会将执行结果作为参数,传递到回调方法中,回调方法无返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    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);
  • 示例代码
    1
    2
    3
    4
    5
    CompletableFuture.supplyAsync(() -> {
    return "Result";
    }).thenAccept((result) -> {
    // TODO 执行任务
    });

接返回值、有返回值

前一个任务执行完成后执行;前一个任务会将执行结果作为参数,传递到回调方法中,并且会调方法有返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    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);
  • 示例代码
    1
    2
    3
    4
    5
    6
    CompletableFuture.supplyAsync(() -> {
    return "Result_1";
    }).thenApply(() -> {
    // TODO 执行任务
    return "Result_2";
    });

接异常、有返回值

某个任务执行异常时执行;异常任务抛出的异常作为参数,传递到回调方法中,并且会调方法有返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn);
    // 使用默认线程池中的线程
    public CompletableFuture<T> exceptionallyAsync(Function<Throwable, ? extends T> fn);
    // 使用自定义线程池中的线程
    public CompletableFuture<T> exceptionallyAsync(Function<Throwable, ? extends T> fn, Executor executor);
  • 示例代码
    1
    2
    3
    4
    5
    6
    CompletableFuture.runAsync(() -> {
    throw new RuntimeException();
    }).exceptionally((exception) -> {
    // TODO 处理异常
    return "ERROR!";
    });

接返回值和异常、无返回值

前一个任务执行完成或出现异常时执行;前一个任务会将结果或抛出的异常作为参数,传递到回调方法中,回调方法无返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    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);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException();
    }).whenCompleteAsync((result, exception) -> {
    if (exception != null) {
    // TODO 处理异常
    } else {
    // TODO 执行任务
    }
    });

接返回值和异常、有返回值

前一个任务执行完成后执行;前一个任务会将结果或抛出的异常作为参数,传递到回调方法中,回调方法有返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    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);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException();
    }).handleAsync((result, exception) -> {
    if (exception != null) {
    // TODO 处理异常
    return "ERROR!";
    } else {
    // 执行任务
    return "SUCCESS!";
    }
    });

两个任务组合

任务转化

将前一个任务的执行结果作为参数进行处理,处理后返回一个新的任务

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
    // 使用默认线程池中的线程
    public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn);
    // 使用自定义线程池中的线程
    public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> {
    return "任务一的结果";
    });

    CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
    return "任务二的结果";
    }).thenComposeAsync((result) -> {
    // TODO 执行任务
    return task;
    });

“且”组合、接返回值、有返回值

将两个任务组合,当两个任务都正常执行完了,将两个任务的结果作为参数,传递到回调方法中,回调方法有返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);
    // 使用默认线程池中的线程
    public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);
    // 使用自定义线程池中的线程
    public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CompletableFuture.supplyAsync(() -> {
    // TODO 任务一
    return "任务一的结果";
    }).thenCombineAsync(CompletableFuture.supplyAsync(() -> {
    // TODO 任务二
    return "任务二的结果";
    }), (result1, result2) -> {
    // 任务一和任务二都完成时执行的回调方法
    return null;
    });

“且”组合、接返回值、无返回值

将两个任务组合,当两个任务都正常执行完了,将两个任务的结果作为参数,传递到回调方法中,回调方法无返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
    // 使用默认线程池中的线程
    public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
    // 使用自定义线程池中的线程
    public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action, Executor executor);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CompletableFuture.supplyAsync(() -> {
    // TODO 任务一
    return "任务一的结果";
    }).thenAcceptBothAsync(CompletableFuture.supplyAsync(() -> {
    // TODO 任务二
    return "任务二的结果";
    }), (result1, result2) -> {
    // TODO 任务一和任务二都完成时执行的回调方法
    });

“且”组合、不接参数、无返回值

将两个任务组合,当两个任务都正常执行完了,执行回调方法,回调方法无返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other, Runnable action);
    // 使用默认线程池中的线程
    public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action);
    // 使用自定义线程池中的线程
    public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action, Executor executor);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CompletableFuture.supplyAsync(() -> {
    // TODO 任务一
    return "任务一的结果";
    }).runAfterBothAsync(CompletableFuture.supplyAsync(() -> {
    // TODO 任务二
    return "任务二的结果";
    }), () -> {
    // TODO 任务一和任务二都完成时执行的回调方法
    });

“或”组合、接返回值、有返回值

将两个任务组合,其中任意一个任务执行完成,将该任务的结果作为参数,传递到回调方法中,回调方法有返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn);
    // 使用默认线程池中的线程
    public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn);
    // 使用自定义线程池中的线程
    public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn, Executor executor);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CompletableFuture.supplyAsync(() -> {
    // TODO 任务一
    return "任务一的结果";
    }).applyToEitherAsync(CompletableFuture.supplyAsync(() -> {
    // TODO 任务二
    return "任务二的结果";
    }), (result) -> {
    // TODO 任务一和任务二任意一个执行完成时执行的回调方法
    return "SUCCESS";
    });

“或”组合、接返回值、无返回值

将两个任务组合,其中任意一个任务执行完成,将该任务的结果作为参数,传递到回调方法中,回调方法无返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action);
    // 使用默认线程池中的线程
    public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action);
    // 使用自定义线程池中的线程
    public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CompletableFuture.supplyAsync(() -> {
    // TODO 任务一
    try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    throw new RuntimeException(e);
    }
    return "任务一的结果";
    }).acceptEitherAsync(CompletableFuture.supplyAsync(() -> {
    // TODO 任务二
    return "任务二的结果";
    }), (result) -> {
    // TODO 任务一和任务二任意一个执行完成时执行的回调方法
    });

“或”组合、不接参数、无返回值

将两个任务组合,其中任意一个任务执行完成,执行回调方法,回调方法无返回值

  • 方法签名
    1
    2
    3
    4
    5
    6
    // 使用调用它的线程上运行(一般是主线程)
    public CompletableFuture<Void> runAfterEither(CompletionStage<?> other, Runnable action);
    // 使用默认线程池中的线程
    public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action);
    // 使用自定义线程池中的线程
    public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action, Executor executor);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CompletableFuture.supplyAsync(() -> {
    // TODO 任务一
    try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    throw new RuntimeException(e);
    }
    return "任务一的结果";
    }).runAfterEitherAsync(CompletableFuture.supplyAsync(() -> {
    // TODO 任务二
    return "任务二的结果";
    }), () -> {
    // TODO 任务一和任务二任意一个执行完成时执行的回调方法
    });

多个任务组合

“任意一个”组合

将多个任务组合,其中任意一个任务执行完成即可拿到该任务的执行结果(执行结果为Object类型),或执行接下来的任务

  • 方法签名
    1
    public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
    return "任务一的结果";
    });

    CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> {
    return "任务二的结果";
    });

    Object result = CompletableFuture.anyOf(task1, task2).join();

“所有”组合

将多个任务组合,当所有任务都执行完成后执行接下来的任务

  • 方法签名
    1
    public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs);
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
    return "任务一的结果";
    });

    CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> {
    return "任务二的结果";
    });

    Object join = CompletableFuture.allOf(task1, task2).join();