Java CompletableFuture 入门到精通

71 阅读2分钟

@[toc]

Java CompletableFuture

参考:juejin.cn/post/714024…

一、CompletableFuture 介绍

CompletableFuture 是 Java 8 中引入的一个新特性,它提供了一种简单的方法来实现异步编程和任务组合。

image-20250325230252701

二、重点方法

1、 创建任务方法
  1. 有返回值:
    • supplyAsync(Supplier<U> supplier)
    • supplyAsync(Supplier<U> supplier, Executor executor)
  2. 无返回值
    • runAsync(Runnable runnable)
    • runAsync(Runnable runnable, Executor executor)
2、结果处理类
  1. 处理结果,返回新值

    • thenApply(Function<? super T,? extends U> fn);
    • thenApplyAsync(Function<? super T,? extends U> fn);
    • thenApplyAsync(Function<? super T,? extends U> fn, Executor executor);
  2. 消费结果,但不返回值

    • thenAccept(Consumer<? super T> action);
    • thenAcceptAsync(Consumer<? super T> action);
    • thenAcceptAsync(Consumer<? super T> action, Executor executor);
  3. 无参,无返回值

    • thenRun(Runnable action);
    • thenRunAsync(Runnable action);
    • thenRunAsync(Runnable action, Executor executor);
  4. 处理结果,实现扁平化嵌套

    • thenCompose (Function<? super T, ? extends CompletionStage<U>> fn);
    • thenComposeAsync (Function<? super T, ? extends CompletionStage<U>> fn);
    • thenComposeAsync (Function<? super T, ? extends CompletionStage<U>> fn, Executor executor);
3、任务组合类
  1. 两个任务执行完,再执行第三个任务,处理结果,也有返回。T+U→R

    • thenCombine (CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);
    • thenCombineAsync (CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);
    • thenCombineAsync (CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor);
  2. 两个任务执行完,再执行第三个任务,处理结果,没有返回

    • thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
      thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
      thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action, Executor executor);
      
  3. 两个任务执行完,再执行第三个,不处理结果,也没有返回

    • runAfterBoth(CompletionStage<?> other, Runnable action);
      runAfterBothAsync(CompletionStage<?> other, Runnable action);
      runAfterBothAsync(CompletionStage<?> other, Runnable action, Executor executor);
      
  4. 两个任务只要有一个完成,就执行任务三,不处理结果,也没返回值

    • runAfterEither(CompletionStage<?> other, Runnable action);
      runAfterEitherAsync(CompletionStage<?> other, Runnable action);
      runAfterEitherAsync(CompletionStage<?> other, Runnable action, Executor executor);
      
  5. 两个任务只要有一个完成,就执行任务三,处理结果,没有返回值

    • acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action);
      acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action);
      acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor);
      
  6. 两个任务只要有一个完成,就执行任务三,处理结果,有返回值

    • applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn);
      applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn);
      applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn, Executor executor);
      
  7. 所有任务完成,适用于并行任务聚合

    • allOf(CompletableFuture<?>... cfs)
  8. 任一任务完成,就返回结果,适用于竞争场景

    • anyOf(CompletableFuture<?>... cfs)
4、异常处理类
  1. 处理异常结果,有返回值

    • exceptionally(Function<Throwable, ? extends T> fn);
  2. 处理正常和异常结果,也有返回值

    • handle(BiFunction<? super T, Throwable, ? extends U> fn);
  3. 处理正常和异常结果,没有返回

    • whenComplete(BiConsumer<? super T, ? super Throwable> action);
      whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
      whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor);
      

三、如何对多线程进行编排

参考:www.yuque.com/hollis666/g…

参考:juejin.cn/post/714024…

四、在 Java 中,如何实现高效的异步编程?如何避免回调地狱?

参考:www.yuque.com/hollis666/g…

  1. 多个任务进行链式调用

image-20250326110424552

  1. 使用 thenCombine()、allOf()、 anyOf() 等方法,并行与组合执行

image-20250326110623820

  1. 使用 exceptionally()handle() 方法处理异常

image-20250326110754261

  1. 链式操作,避免回调地狱

image-20250326110914009

  1. 使用 whenCompletehandle 处理任务结果和异常

image-20250326111015232

  1. 使用 allOf()anyOf() 合并多个任务

image-20250326111055780

  1. 使用 ExecutorService 配合 CompletableFuture进行并发执行

image-20250326111133305

五、如何实现主线程捕获子线程异常

参考:www.yuque.com/hollis666/g…

参考:Java 八股/03-Java 并发/为什么不能在try-catch中捕获子线程的异常?.md

你可以使用 CompletableFuture.supplyAsync() 来执行任务,并使用handle()方法捕获异常

image-20250326111658512