CompletableFuture 是 Java 8 引入的 异步编程核心工具类,它实现了 Future 和 CompletionStage 接口,提供了强大且灵活的方式来处理异步非阻塞任务,支持任务编排、链式调用、异常处理、合并多个异步结果等。
✅ 一、什么是 CompletableFuture?原生支持异步编程?
CompletableFuture是 Java 原生支持的 异步编程模型(Asynchronous Programming Model),它允许你:
- 在不阻塞主线程的情况下执行耗时操作(如网络请求、数据库查询、文件读取等)。
- 通过回调机制在任务完成后自动执行后续逻辑。
- 将多个异步任务组合、串行或并行执行。
它解决了传统 Future 的痛点:不能手动完成、无法链式调用、难以组合多个任务。
✅ 二、CompletableFuture 的核心作用
| 作用 | 说明 |
|---|---|
| 🔹 异步执行 | 不阻塞主线程,提升系统吞吐量 |
| 🔹 回调机制 | 任务完成后自动执行 thenApply、thenAccept 等回调 |
| 🔹 任务编排 | 支持串行(thenCompose)、并行(thenCombine)、聚合(allOf / anyOf) |
| 🔹 异常处理 | 提供 exceptionally、handle 等方法统一处理异常 |
| 🔹 手动完成 | 可通过 complete() 手动设置结果(用于模拟或测试) |
✅ 三、常用方法一览(附作用说明)
| 方法 | 作用 |
|---|---|
supplyAsync(Supplier<T>) | 异步执行有返回值的任务(使用默认线程池) |
runAsync(Runnable) | 异步执行无返回值的任务 |
thenApply(Function<T,R>) | 上一阶段结果 → 转换为新结果(同步) |
thenApplyAsync(Function<T,R>) | 同上,但在异步线程中执行 |
thenAccept(Consumer<T>) | 接收上一阶段结果,执行消费逻辑(无返回) |
thenRun(Runnable) | 上一阶段完成后执行 Runnable(不关心结果) |
thenCombine(CompletableFuture, BiFunction) | 合并两个异步任务的结果 |
thenCompose(Function<CF>) | 串行化异步任务(flatMap 风格) |
exceptionally(Function<Throwable,T>) | 捕获异常并返回默认值 |
handle(BiFunction<T,Throwable,R>) | 无论成功或失败都执行的回调 |
whenComplete(BiConsumer<T,Throwable>) | 最终回调(类似 finally) |
allOf(CompletableFuture...) | 所有任务都完成才结束(返回 CompletableFuture<Void>) |
anyOf(CompletableFuture...) | 任一任务完成即结束 |
✅ 四、综合性使用示例(模拟电商下单流程)
以下是一个具有实际开发参考意义的完整示例,模拟一个电商系统中“用户下单”时的异步流程:
- 校验库存
- 计算价格(含优惠券)
- 扣减库存
- 发送订单通知
- 合并结果并返回订单信息
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CompletableFutureExample {
// 自定义线程池(生产环境推荐使用,避免使用默认 ForkJoinPool)
private static final ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
System.out.println("【用户下单流程开始】");
// 启动异步下单流程
CompletableFuture<OrderResult> orderFuture = placeOrderAsync("user123", "item001", 2, "COUPON_10");
// 主线程可以继续做其他事(非阻塞)
System.out.println("主线程:订单已提交,正在处理...");
// 模拟主线程其他工作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 获取最终结果(实际开发中可能通过回调处理,而非阻塞等待)
try {
OrderResult result = orderFuture.get(5, TimeUnit.SECONDS); // 设置超时
System.out.println("✅ 下单成功:" + result);
} catch (Exception e) {
System.err.println("❌ 下单失败:" + e.getMessage());
} finally {
executor.shutdown(); // 关闭线程池
}
}
/**
* 异步下单主流程
*/
public static CompletableFuture<OrderResult> placeOrderAsync(
String userId, String itemId, int quantity, String couponCode) {
// 1. 异步校验库存(有返回值)
CompletableFuture<Boolean> checkStock = CompletableFuture
.supplyAsync(() -> {
System.out.println("异步任务1:校验库存...");
sleep(800); // 模拟耗时
if ("item001".equals(itemId) && quantity <= 10) {
System.out.println("✅ 库存充足");
return true;
} else {
throw new RuntimeException("库存不足");
}
}, executor);
// 2. 异步计算价格(依赖优惠券,可与库存并行)
CompletableFuture<Double> calculatePrice = CompletableFuture
.supplyAsync(() -> {
System.out.println("异步任务2:计算价格...");
sleep(600);
double basePrice = 100.0;
double discount = "COUPON_10".equals(couponCode) ? 10.0 : 0.0;
double finalPrice = (basePrice * quantity) - discount;
System.out.println("💰 最终价格:" + finalPrice);
return finalPrice;
}, executor);
// 3. 只有库存校验通过后,才扣减库存(串行依赖)
CompletableFuture<String> deductStock = checkStock
.thenApplyAsync(isValid -> {
if (Boolean.TRUE.equals(isValid)) {
System.out.println("异步任务3:扣减库存...");
sleep(400);
return "SUCCESS";
}
return "FAILED";
}, executor);
// 4. 合并库存和价格结果,生成订单信息
CompletableFuture<OrderResult> createOrder = deductStock
.thenCombine(calculatePrice, (stockResult, price) -> {
if ("SUCCESS".equals(stockResult)) {
System.out.println("异步任务4:创建订单...");
sleep(200);
return new OrderResult(
"ORDER_" + System.currentTimeMillis(),
userId,
price,
"PAID"
);
} else {
throw new RuntimeException("扣减库存失败");
}
});
// 5. 发送订单通知(不阻塞主流程)
createOrder
.thenAcceptAsync(order -> {
System.out.println("异步任务5:发送订单通知给用户 " + order.userId);
sleep(300);
System.out.println("📧 通知发送成功");
}, executor)
.exceptionally(ex -> {
System.err.println("⚠️ 发送通知失败:" + ex.getMessage());
return null;
});
// 6. 异常处理:任何阶段出错,返回默认结果或抛出
CompletableFuture<OrderResult> finalFuture = createOrder
.exceptionally(ex -> {
System.err.println("🛒 下单流程异常:" + ex.getMessage());
return new OrderResult("FAILED", userId, 0.0, "CANCELLED");
});
// 7. 最终回调(类似 finally)
finalFuture.whenComplete((result, throwable) -> {
if (throwable != null) {
System.err.println("🔚 流程结束,异常:" + throwable.getMessage());
} else {
System.out.println("🔚 流程结束,订单号:" + result.orderId);
}
});
return finalFuture;
}
/**
* 模拟耗时操作
*/
private static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* 订单结果类
*/
static class OrderResult {
String orderId;
String userId;
double amount;
String status;
public OrderResult(String orderId, String userId, double amount, String status) {
this.orderId = orderId;
this.userId = userId;
this.amount = amount;
this.status = status;
}
@Override
public String toString() {
return "OrderResult{" +
"orderId='" + orderId + '\'' +
", userId='" + userId + '\'' +
", amount=" + amount +
", status='" + status + '\'' +
'}';
}
}
}
✅ 五、输出示例(可能顺序略有不同)
【用户下单流程开始】
主线程:订单已提交,正在处理...
异步任务1:校验库存...
异步任务2:计算价格...
✅ 库存充足
💰 最终价格:190.0
异步任务3:扣减库存...
异步任务4:创建订单...
异步任务5:发送订单通知给用户 user123
📧 通知发送成功
🔚 流程结束,订单号:ORDER_1743859200123
✅ 下单成功:OrderResult{orderId='ORDER_1743859200123', userId='user123', amount=190.0, status='PAID'}
✅ 六、实际开发中的最佳实践
| 实践 | 说明 |
|---|---|
| ✅ 使用自定义线程池 | 避免使用默认 ForkJoinPool,防止任务阻塞影响其他模块 |
| ✅ 设置超时 | 使用 get(timeout, unit) 防止无限等待 |
| ✅ 异常处理 | 必须使用 exceptionally 或 handle 处理异常,否则异常会“消失” |
| ✅ 避免阻塞主线程 | 尽量使用 thenAccept 等回调,而非 get() |
| ✅ 任务聚合 | 使用 CompletableFuture.allOf() 等待多个任务完成 |
| ✅ 日志追踪 | 在异步任务中传递上下文(如 traceId),便于排查问题 |
✅ 七、总结
CompletableFuture 是 Java 原生异步编程的核心工具,它让你可以:
- 轻松实现非阻塞调用
- 高效编排复杂业务流程
- 提升系统吞吐量和响应速度
在微服务、高并发、IO 密集型场景(如电商、支付、网关)中,CompletableFuture 是提升性能和用户体验的关键技术。
🚀 推荐在 Spring Boot、Vert.x、Quarkus 等框架中结合使用,构建高性能异步系统。
3385

被折叠的 条评论
为什么被折叠?



