1. CompletableFuture 简介
- JUC 中提供的一个实现异步编程的工具类。实现了 Future 和 CompletionStage 两个接口,主要用作于创建,组合,处理多个异步任务
- 核心思想是 异步任务的链式处理
2. CompletableFuture 与 Future 的区别
传统的 Future 接口在获取结果时,如果任务未完成,会阻塞,直到任务完成,或超时。 Future 的 缺点如下
-
无法主动通知任务完成
只能通过手动调用 get 方法 来阻塞线程获取结果
-
无法进行任务组合
多个 Future 任务不能组合在一起进行复杂的依赖处理
-
没有回调机制
而 CompletableFuture 引入了 非阻塞 与 回调机制
3. CompletableFuture 常用 API
3.1 创建 CompletableFuture 实例对象的方法
- CompletableFuture.supplyAsync()
- 有返回值的
- CompletableFuture.runAsync()
- 无返回结果
这两个方法,都可以传入自定义线程池
3.2 组合与处理异步结果
-
基本回调方法
-
thenApply(Function)
当任务完成时,应用指定的函数对结果进行转换,并返回一个新的 CompletableFuture
future.thenApply(result -> result + " processed")
-
thenAccept(Consumer)
任务完成时,执行指定的动作,对结果进行消费,无返回值
future.thenAccept(result -> System.out.println("Result: " + result))
-
thenRun(Runnable)
任务完成时,执行一个 Runnable, 但不处理结果
future.thenRun(() -> System.out.println("Task finished"))
-
-
合并与组合任务
-
thenCombine()
合并两个独立的 CompletableFuture,当都完成时,执行一个 BiFunction 进行处理,并返回一个新的 CompletableFuture
future1.thenCombine(future2, (res1, res2) -> res1 + res2)
-
thenCompose()
类似于 flatMap,将两个 CompletableFuture 链接起来,第一个 CompletableFuture 完成时,将其结果作为输入参数交给下一个 CompletableFuture。
future1.thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " combined"))
-
anyOf() 和 allOf()
- anyOf():当任意一个 CompletableFuture 完成时返回(常用于“只要有一个任务完成”时)。
- allOf():当所有 CompletableFuture 都完成时返回(常用于“等待所有任务完成”时)。
-
-
异常处理
a. exceptionally(Function<Throwable, ? extends T>)
如果 CompletableFuture 执行期间抛出了异常,则使用指定的函数处理异常,并返回一个默认值。
future.exceptionally(ex -> "Error occurred: " + ex.getMessage())
b. handle(BiFunction<T, Throwable, R>)
无论任务成功或失败,均会触发该方法,接收 result 和 Throwable 两个参数。
future.handle((result, ex) -> ex == null ? result : "Error: " + ex.getMessage())
-
阻塞获取结果
尽管 CompletableFuture 更推荐使用回调方法处理结果,但有时我们需要阻塞获取最终结果,可以使用以下方法:
- get():阻塞等待,直到 CompletableFuture 完成。
- get(long timeout, TimeUnit unit):带超时限制的阻塞获取。
- join():与 get() 类似,但不会抛出 Checked Exception。
4. CompletableFuture 的应用场景
4.1 异步任务的链式处理
使用 thenApply()、thenAccept() 和 thenRun() 方法,可以将多个任务串联起来进行顺序执行,实现异步任务的链式处理。
4.2 并行任务的合并与汇总
CompletableFuture.allOf() 可以用于等待所有任务完成,thenCombine() 和 thenCompose() 可以将多个异步任务的结果合并。
4.3 异常处理与结果回退
使用 exceptionally()、handle() 等方法,可以优雅地处理异步任务执行过程中的异常情况。
4.4 异步任务的超时控制
可以通过 orTimeout() 和 completeOnTimeout() 方法实现对异步任务的超时控制。
5. 代码示例
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建一个异步任务
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello";
});
// 创建另一个异步任务,并将两个结果进行合并
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "World";
});
// 合并两个任务结果
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (res1, res2) -> res1 + " " + res2);
// 处理合并后的结果
combinedFuture.thenAccept(result -> System.out.println("Result: " + result));
// 异常处理
CompletableFuture<String> exceptionHandledFuture = combinedFuture.exceptionally(ex -> "Error: " + ex.getMessage());
// 阻塞获取最终结果
System.out.println("Final Result: " + exceptionHandledFuture.get());
}
}