Java CompletableFuture:异步编程的利器
1、CompletableFuture 概述
CompletableFuture 是 Java 8 引入的一个强大的异步编程工具,位于 java.util.concurrent 包中。它实现了 Future 接口,并提供了丰富的异步操作方法,使得异步编程变得更加简单和优雅。
核心特性:
- 异步执行任务,不阻塞主线程
- 支持链式调用,代码更简洁
- 提供丰富的组合操作方法
- 支持异常处理和回调
- 可以手动完成或取消任务
与 Future 的区别:
- Future 只能通过 get() 方法阻塞获取结果
- CompletableFuture 支持回调函数,无需阻塞等待
- CompletableFuture 提供了更多的组合和转换方法
- CompletableFuture 支持异常处理和恢复
2、基本使用方法
2.1、创建 CompletableFuture
创建异步任务:
// 使用 supplyAsync 创建有返回值的异步任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "Hello, CompletableFuture!";
});
// 使用 runAsync 创建无返回值的异步任务
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("执行异步任务");
});
// 使用自定义线程池
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return "使用自定义线程池";
}, executor);2.2、获取结果
// 阻塞获取结果(不推荐)
String result = future.get();
// 阻塞获取结果,设置超时时间
String result = future.get(5, TimeUnit.SECONDS);
// 立即获取结果,如果未完成则返回默认值
String result = future.getNow("默认值");
// 非阻塞获取结果(推荐)
future.thenAccept(result -> {
System.out.println("结果:" + result);
});3、异步编程模式
3.1、链式调用
CompletableFuture 提供了丰富的链式调用方法,使得异步任务的组合变得简单:
// thenApply:转换结果
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> "123")
.thenApply(Integer::parseInt)
.thenApply(num -> num * 2);
// thenAccept:消费结果,无返回值
CompletableFuture.supplyAsync(() -> "Hello")
.thenAccept(result -> System.out.println(result));
// thenRun:执行后续操作,不关心前一步的结果
CompletableFuture.supplyAsync(() -> "Hello")
.thenRun(() -> System.out.println("任务完成"));
// thenCompose:连接两个 CompletableFuture
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " World"));
// thenCombine:组合两个独立的 CompletableFuture
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> result = future1.thenCombine(future2, (a, b) -> a + b);3.2、多任务组合
// allOf:等待所有任务完成
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "任务1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "任务2");
CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
// anyOf:任意一个任务完成即可
CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);4、异常处理
CompletableFuture 提供了多种异常处理方法,确保程序的健壮性:
4.1、异常捕获
// exceptionally:捕获异常并提供默认值
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) throw new RuntimeException("发生错误");
return 100;
}).exceptionally(ex -> {
System.out.println("异常:" + ex.getMessage());
return 0; // 返回默认值
});
// handle:处理正常结果和异常
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (true) throw new RuntimeException("发生错误");
return 100;
}).handle((result, ex) -> {
if (ex != null) {
System.out.println("异常:" + ex.getMessage());
return 0;
}
return result;
});
// whenComplete:处理完成事件,不改变结果
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100)
.whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("异常:" + ex.getMessage());
} else {
System.out.println("结果:" + result);
}
});5、实际应用场景
5.1、并行调用多个服务
public CompletableFuture<UserInfo> getUserInfo(Long userId) {
// 并行调用多个服务
CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> userService.getUser(userId));
CompletableFuture<List<Order>> ordersFuture = CompletableFuture.supplyAsync(() -> orderService.getOrders(userId));
CompletableFuture<Account> accountFuture = CompletableFuture.supplyAsync(() -> accountService.getAccount(userId));
// 组合结果
return CompletableFuture.allOf(userFuture, ordersFuture, accountFuture)
.thenApply(v -> {
UserInfo userInfo = new UserInfo();
userInfo.setUser(userFuture.join());
userInfo.setOrders(ordersFuture.join());
userInfo.setAccount(accountFuture.join());
return userInfo;
});
}5.2、异步任务链
public CompletableFuture<OrderResult> processOrder(OrderRequest request) {
return CompletableFuture.supplyAsync(() -> validateOrder(request))
.thenCompose(order -> saveOrder(order))
.thenCompose(order -> paymentService.process(order))
.thenCompose(payment -> sendNotification(payment))
.exceptionally(ex -> {
log.error("订单处理失败", ex);
return OrderResult.failed(ex.getMessage());
});
}5.3、超时处理
// 使用 orTimeout 设置超时(Java 9+)
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> slowOperation())
.orTimeout(5, TimeUnit.SECONDS)
.exceptionally(ex -> "操作超时");
// 使用 completeOnTimeout 设置超时默认值(Java 9+)
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> slowOperation())
.completeOnTimeout("默认值", 5, TimeUnit.SECONDS);6、最佳实践与总结
6.1、线程池选择
- 默认使用 ForkJoinPool.commonPool(),适合计算密集型任务
- IO 密集型任务应使用自定义线程池
- 避免在异步任务中执行阻塞操作
6.2、异常处理
- 始终添加异常处理逻辑
- 使用 exceptionally 或 handle 方法捕获异常
- 记录异常日志,便于问题排查
6.3、性能优化
- 合理设置线程池大小
- 避免创建过多的 CompletableFuture
- 使用 thenCompose 而非 thenApply 来连接异步任务
- 注意内存泄漏,及时释放资源
6.4、注意事项
- CompletableFuture 的回调方法默认在执行任务的线程中运行
- 可以使用 thenApplyAsync 等方法指定回调执行的线程池
- 注意任务的取消和超时处理
- 避免在回调中执行耗时操作
6.5、总结
CompletableFuture 是 Java 异步编程的核心工具,它提供了丰富的 API 来处理异步任务。通过合理使用 CompletableFuture,可以显著提升应用的性能和响应能力。
关键要点:
- 使用 supplyAsync 和 runAsync 创建异步任务
- 使用链式调用简化异步代码
- 使用 allOf 和 anyOf 组合多个任务
- 始终添加异常处理逻辑
- 选择合适的线程池
掌握 CompletableFuture 的使用,对于构建高性能、高并发的 Java 应用至关重要。它不仅简化了异步编程的复杂度,还提供了强大的组合和错误处理能力,是现代 Java 开发者必备的技能之一。

