Java 原生异步编程 CompletableFuture 的介绍和使用

CompletableFuture 是 Java 8 引入的 异步编程核心工具类,它实现了 FutureCompletionStage 接口,提供了强大且灵活的方式来处理异步非阻塞任务,支持任务编排、链式调用、异常处理、合并多个异步结果等。


✅ 一、什么是 CompletableFuture?原生支持异步编程?

CompletableFuture 是 Java 原生支持的 异步编程模型(Asynchronous Programming Model),它允许你:

  • 在不阻塞主线程的情况下执行耗时操作(如网络请求、数据库查询、文件读取等)。
  • 通过回调机制在任务完成后自动执行后续逻辑。
  • 将多个异步任务组合、串行或并行执行。

它解决了传统 Future 的痛点:不能手动完成、无法链式调用、难以组合多个任务


✅ 二、CompletableFuture 的核心作用

作用说明
🔹 异步执行不阻塞主线程,提升系统吞吐量
🔹 回调机制任务完成后自动执行 thenApplythenAccept 等回调
🔹 任务编排支持串行(thenCompose)、并行(thenCombine)、聚合(allOf / anyOf
🔹 异常处理提供 exceptionallyhandle 等方法统一处理异常
🔹 手动完成可通过 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) 防止无限等待
✅ 异常处理必须使用 exceptionallyhandle 处理异常,否则异常会“消失”
✅ 避免阻塞主线程尽量使用 thenAccept 等回调,而非 get()
✅ 任务聚合使用 CompletableFuture.allOf() 等待多个任务完成
✅ 日志追踪在异步任务中传递上下文(如 traceId),便于排查问题

✅ 七、总结

CompletableFuture 是 Java 原生异步编程的核心工具,它让你可以:

  • 轻松实现非阻塞调用
  • 高效编排复杂业务流程
  • 提升系统吞吐量和响应速度

在微服务、高并发、IO 密集型场景(如电商、支付、网关)中,CompletableFuture 是提升性能和用户体验的关键技术。

🚀 推荐在 Spring Boot、Vert.x、Quarkus 等框架中结合使用,构建高性能异步系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值