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

ROS环境下UR机械臂与Realsense相机手眼标定实战指南 本文提供了在ROS环境下,对UR机械臂与Realsense相机进行手眼标定的完整实战指南。详细介绍了从环境搭建、软件包安装、硬件配置到分步数据采集与计算的完整流程,并分享了常见的避坑技巧与精度优化方法,旨在帮助开发者高效、准确地完成标定,为后续的机器人视觉应用奠定坚实基础。 阅读详情

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 等框架中结合使用,构建高性能异步系统。

【软件使用】Calibre部分提参的实战技巧与常见问题解析 本文详细解析了Calibre部分提参(Partial PEX)的实战技巧,重点介绍了如何利用HCELL与XCELL文件高效排除已知模块,实现精准的寄生参数提取,从而快速定位后仿真中的时序与信号完整性问题。文章涵盖了从图形界面到命令行的完整操作流程,并提供了常见问题(如时钟失真、模块“消失”)的深度Debug指南与最佳实践,助力芯片设计工程师提升验证效率。 阅读详情

相关推荐

数字IC笔记-低功耗技术

传统的降低Power的方法主要有: 1.门控时钟技术(clock gating) 2.多阈值电压技术(MultiShreshold) 3.动态电压频率调节技术(DVFS) 目前有以下几种低功耗技术: 1.多电压技术(Multi-Voltage) 2.MTCOMS Power Gating 技术(多阈值功耗控制技术),比如基带部分中的2G、3G、CDMA、LTE等通过awake—>sleep—>awake的方式间歇式的打开或关断其电源,power gating 可以完全关掉dynamic的pow

sinat_41774721的博客 1932

CompletableFuture类的简介

用于在 I/O 操作完成时回调通知,它通常更适合用于异步 I/O(例如文件 I/O、网络 I/O),因为它不涉及任务的组合或链式调用,仅仅是任务完成后的回调。它提供了大量的异步任务控制方法,并且支持链式调用、组合任务、异常处理等功能,使得异步编程更加简洁和可读。主要是处理计算任务的异步结果,而 AIO 的 I/O 操作本身就是基于回调模式,因此不太适合使用。提供了丰富的 API 来控制异步任务的执行顺序、结果组合和异常处理,适合异步计算的编排。,因为它专门用于异步 I/O 操作,回调方式更合适。

fqlya的博客 899

红外协议 IR NEC 协议深度解析-简单易懂协议详解

1. 协议特征 使用双向编码(又称曼彻斯特编码); 使用38K载波对编码后的波形进行调制; 位时间 1.12ms 或 2.25ms 2. 调制 定义脉冲560µS为脉冲基本宽度T; 根据脉冲时间长短来解码。推荐载波占空比为1/3至1/4: (1) Logic “1” 位宽为2.25ms,脉冲时间560us(T + 3T); (2) Logic “0” 位宽为1.12ms,脉冲时间560us(T + T)。 (3 ) 重复码: 位宽为11.25ms,脉冲时间9ms(16T + 4T)。 3. 协议

代码打工人的博客 1万+

CompletableFuture的使用(详细)

completablefuture

m0_72410274的博客 2240

贝加莱Automation Studio 4.10安装保姆级教程:从官网下载到解决.Net 3.5报错

本文提供贝加莱Automation Studio 4.10的详细安装教程,涵盖从官网下载到解决.Net 3.5报错的全过程。特别针对工业自动化开发环境中常见的.Net Framework 3.5安装问题,提供多种经过验证的解决方案,包括控制面板安装、DISM命令离线安装和手动下载安装包等方法,帮助工程师顺利完成PLC开发环境的搭建。

weixin_30955617的博客 709

【学习记录】IIC驱动ICM42670+卡尔曼滤波+四元数姿态角解算

ICM42670陀螺仪可以使用iic驱动,单片机平台使用GD32f305VE。

liarsup的博客 8260

CompletableFuture是什么?有什么用?

比如你现在有一个打车的项目,首先我们下单,系统会调用订单服务,其中涉及的操作有发送通知,计算费用,更新订单状态,正常情况下,如果不进行异步化,我们采取主线程一个个的执行这些操作,等这些操作执行完,才会给用户返回响应,这种效率就很低了。例如,当有新订单时,主线程无需等待通知发送完成、费用计算结束以及状态更新完毕,就可以接着处理下一个订单请求,提升了整体的处理效率。比如,在计算费用之前需要先获取行程信息,通过链式调用可以确保获取行程信息的任务完成后,才会执行计算费用的任务。:可以处理任务之间的依赖关系。

2301_77396759的博客 352

物联网组网技术优缺点对比:蓝牙、LoRa、wifi、NB-IoT、ZigBee等

1.前言 最近对物联网产品自组网技术选型,找到合适的组网技术,让产品自行组网并完成数据的传输。 2.参数对比

谁念西风独自凉 4万+

CompletableFuture的使用

CompletableFuture解决的问题: 总的来说,就是 解决future模式的缺点。主要是 a. 为了解决Future虽然可以实现异步获取线程的执行结果,但是future没有提供通知机制,调用方无法得知future什么时候执行完的问题。 b.要么使用阻塞, 在future.get()的地方等待future返回结果,这时会变成同步操作。如果使用isDone()方法进行循环判断,就会消耗...

有料,有味,很重要 7467

使用CUDA进行按流排序的内存分配的示例程序

在GPU编程中,按流排序的内存分配是一种常见的优化技术,它可以提高内存访问的效率。通过将内存分配与特定的CUDA流相关联,可以确保在GPU上的并发操作期间,内存分配操作与其他GPU计算操作同时进行,从而减少了潜在的内存访问延迟。请注意,上述示例中的代码仅供参考,并可能需要根据实际需求进行修改和调整。此外,为了完整性,我们省略了一些细节,例如主机指针的分配和释放,以及错误处理和错误检查等。在该示例中,我们创建了4个CUDA流,并使用内存池进行内存分配。然后,我们在每个流上执行了相应的内存访问操作,并使用。

Byte_O_O的博客 281

群无人机航迹规划-虚拟管道

图源北理工全权老师团队虚拟管道相关论文,文字为个人理解,以ppt形式分享报告。

coldmood77的博客 668

Java并发原生工具:异步编程工具 (CompletableFuture)

CompletableFuture是Java 8引入的异步编程工具,支持链式回调、并行聚合和异常处理,适用于高并发场景。

乐只悠悠 355

解决TexStudio编写LaTeX论文引用文献问题:正文引用处出现[?],参考文献也不显现

当我们利用LaTeX编写论文时,可能会出现引用参考文献时正文引用处出现?号,肯能的原因及解决方案如下: 问题一 忘记在\end{document}前面放\bibliographystyle{样式}和\bibliography{参考文献bib文件名}: \bibliographystyle{plain} \bibliography{sample} 其中, LaTeX 标准选项及其样式共有以下8种: plain,按字母的顺序排列,比较次序为作者、年度和标题. unsrt,样式同plain,只是按照引用的先后

左手の明天的博客 9527

Java 原生异步编程与Spring 异步编程 详解

Java异步编程是现代高性能应用开发的核心技术,主要分为同步和异步两种方式。同步任务按顺序执行,会阻塞主线程;异步任务则并行执行,提高系统吞吐量。Java原生支持手动创建线程和使用ExecutorService线程池管理异步任务,后者能复用线程减少开销。常用线程池类型包括FixedThreadPool(固定线程数)、CachedThreadPool(自动扩容)和ScheduledThreadPool(定时任务),适用于不同场景。异步编程解决了同步方式的阻塞问题,但需注意线程管理和资源消耗。

1486

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: Spring MVC 拦截器(HandlerInterceptor)深度解析与实战指南
下一篇: String 常用方法总揽(按功能分类)
龙茶清欢
博客等级 码龄7年 3720粉丝 375原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

龙茶清欢

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

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

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

打赏作者

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

抵扣说明:

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

余额充值