CompletionStage 的异常处理

news/2025/3/25 23:21:12/文章来源:https://www.cnblogs.com/bestjosephine/p/18792567

CompletionStage 的异常处理

1. 异常处理流程

flowchart TDA[Stage1: 异步任务] -->|正常完成| B[Stage2: 处理结果]A -->|抛出异常| C[Stage2: 捕获异常]C -->|whenComplete| D[记录日志/清理资源\n不改变结果]C -->|handle| E[返回替代结果\n覆盖异常]D -->|继续传递异常| F[后续阶段仍收到异常]E -->|替换为正常结果| G[后续阶段使用新值]

2. 关键方法对比

方法 作用 是否改变结果 示例
whenComplete 记录日志,但保留原结果/异常 ❌ 不改变 stage.whenComplete((res, ex) -> log(ex))
handle 处理异常并返回替代结果 ✔️ 改变 stage.handle((res, ex) -> ex != null ? 0 : res)
exceptionally 仅处理异常,返回默认值 ✔️ 改变 stage.exceptionally(ex -> 0)

3. 分步骤详解(含代码)

场景模拟

假设有一个异步任务可能成功或失败:

CompletableFuture<Integer> stage1 = CompletableFuture.supplyAsync(() -> {if (Math.random() > 0.5) {return 10; // 正常完成} else {throw new RuntimeException("Oops!"); // 故意抛出异常}
});

方式1:未处理异常(直接崩溃)

stage1.thenApply(x -> x * 2) // 若 stage1 异常,此处不执行.thenAccept(System.out::println);
  • 流程图
    flowchart LRA[Stage1 异常] --> B[thenApply 被跳过]B --> C[thenAccept 被跳过]C --> D[整个链异常结束]
  • 结果:整个调用链因异常终止,无输出。

方式2:使用 whenComplete(记录异常,但结果不变)

stage1.whenComplete((result, ex) -> {if (ex != null) {System.out.println("Stage1 异常: " + ex.getMessage());}}).thenApply(x -> x * 2) // 若 stage1 异常,此处接收 null 并抛出 NPE.thenAccept(System.out::println);
  • 流程图
    flowchart LRA[Stage1 异常] --> B[whenComplete 记录日志]B -->|传递原异常| C[thenApply 接收 null → NPE]C --> D[整个链再次异常]
  • 结果
    Stage1 异常: Oops!
    抛出 NullPointerException(因为 thenApply 接收 null)
    

方式3:使用 handle(替换异常为默认值)

stage1.handle((result, ex) -> {if (ex != null) {System.out.println("Stage1 异常,返回 0");return 0; // 替换异常为默认值}return result;}).thenApply(x -> x * 2) // 0 → 0.thenAccept(System.out::println); // 输出 0
  • 流程图
    flowchart LRA[Stage1 异常] --> B[handle 返回 0]B -->|传递新值| C[thenApply 0 → 0]C --> D[输出 0]
  • 结果
    Stage1 异常,返回 0
    0
    

方式4:使用 exceptionally(仅处理异常)

stage1.exceptionally(ex -> {System.out.println("Stage1 异常,返回 -1");return -1;}).thenApply(x -> x * 2) // -1 → -2.thenAccept(System.out::println); // 输出 -2
  • 流程图
    flowchart LRA[Stage1 异常] --> B[exceptionally 返回 -1]B --> C[thenApply -1 → -2]C --> D[输出 -2]
  • 结果
    Stage1 异常,返回 -1
    -2
    

4. 对比总结

场景 whenComplete handle exceptionally
是否改变结果 不改变(只记录) 可返回新值覆盖异常 仅异常时返回默认值
后续阶段接收内容 原结果或异常 新结果或异常 新结果或异常
典型用途 日志记录、资源清理 异常恢复 简化异常处理

5. 最佳实践

  1. 明确处理边界

    • 在链式调用中尽早处理异常(如 handleexceptionally),避免异常扩散。
    stage1.handle(...) // 第一个处理点.thenApply(...).thenAccept(...);
    
  2. 区分 whenComplete 和 handle

    • 需要 只记录不修复 时用 whenComplete
    • 需要 修复异常并继续 时用 handle
  3. 避免 NPE

    • 如果使用 whenComplete,确保后续阶段能处理可能的 null 值。

最终结论
CompletionStage 的异常处理像一个「管道中的错误传递」——如果不主动处理,异常会一直传递到链的末端;而通过 handle/exceptionally 可以像「阀门」一样截断异常,替换为正常值继续流动。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/905713.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

矿山皮带运输机安全监测预警系统

智慧矿山皮带运输机安全监测预警系统是基于AI视频监测分析识别的智能皮带管理系统,该系统通过将人工智能识别算法提高实时分析的效率,达到现场快速识别、分析、预警的目的,为矿山皮带运输系统提供可视化的安全生产保障,该系统已经实现了皮带运输机大媒块、传输带异物、传输…

OP253自动安装凸轮弹簧常见问题

1.夹爪抓取弹簧后不停扔料 两台弹簧振动盘里面的弹簧是镜像件,如果出现混料被取走,会导致卷簧时卡死。夹爪夹住弹簧并提起时,有两个接近开关会检测弹簧是否正确,如果不正确,会将弹簧扔进废料桶。上图两个接近开关是埋入式,只有中心位置检测。应该左边不亮,右边亮,如果任…

web作业

制作一个学生管理系统包括按钮和输入框学生成绩管理系统body { font-family: Arial, sans-serif; margin: 20px } \3c pre>\3c code> h1 { text-align: center } .add-student, .search, .filters { margin-bottom: 20px } table { width: 100%; border-collapse: col…

linux主机新增硬盘与挂载

近期对工作站主机新增了硬盘,网上搜罗了一些教程,整合了一下,感谢相关博主的知识分享,本篇只是整合参考:https://zhuanlan.zhihu.com/p/117651379 https://cn.linux-console.net/?p=10440新增硬盘处理 新增硬盘后,在linux系统下输入 fdisk -l 命令查看当前磁盘信息可以看…

如何优化SQL查询以提高数据库性能?

你正在自助餐厅,所有的食物看起来都很美味。但你不是拿一个盘子,只取你需要的,而是开始从各个角落堆满食物,弄得一团糟,速度也慢了下来。结果是什么?你拿的东西很多并且效率低下。 这就像没有优化的SQL查询!它们加载了不必要的数据,拖慢了整个系统的速度,并在数据库中…

HTB Season7 Dog

一、信息收集 拿到ip,先测试一下连通性连通性正常,使用nmap扫描一下ip,输入nmap -sV -sC -A 10.10.11.58 -Pn 扫描发现http页面,并且发现了网页使用了BackDropCMS在hosts内添加添加页面,访问网页发现一个登录框,尝试一下sql注入无果,只能另寻出路此时dirsearch扫描发现了…

20242802 2023-2024-2《网络攻防实践》第四周作业

20242802 2023-2024-2 《网络攻防实践》第四周作业 1.实验内容与知识点整理TCP/IP参考模型 在TCP/IP参考模型中,去掉了OSI参考模型中的会话层和表示层(这两层的功能被合并到应用层实现)。同时将OSI参考模型中的数据链路层和物理层合并为主机到网络层,所以在TCP/IP参考模型中…

浅谈--Cache Design Pattern

🤔听说你用过Redis、Caffeine,那我问你你了解Cache Design Pattern吗?Look at my eyes。 今天就来聊聊Cache Design Pattern。Cache Design Pattern是缓存设计模式,是用于优化系统性能、减少资源消耗和提升响应速度的软件架构策略。主要有六大核心缓存模式。 Cache-Aside …

七、神经网络-非线性激活

小土堆视频:https://www.bilibili.com/video/BV1hE411t7RN?spm_id_from=333.788.videopod.episodes&vd_source=6cb513d59bf1f73f86d4225e9803d47b&p=19非线性变换的主要目的:引入非线性能力,使模型能够学习复杂的映射关系。如果没有非线性激活,神经网络本质上相当…

日报2025325

今日继续学习springboot,已实现springboot+vue的前后端跨域连接关键是配置CorsConfig以及Requestjs

15. SD卡

一、SD卡简介SD 卡的规范由 SD 卡协会明确,可以访问 https://www.sdcard.org 查阅更多标准。SD 卡主要有 SD、Mini SD 和 microSD(原名 TF 卡,2004 年正式更名为 Micro SD Card)三种类型,Mini SD 已经被 microSD 取代。上述表格的 “脚位数”,对应于实卡上的 “金手指” …

20242321 2024-2025-2 《Python程序设计》实验一报告(修改版)

20242321 2024-2025-2 《Python程序设计》实验一报告(修改版) 课程:《Python程序设计》 班级: 2423 姓名:汤泽鹏 学号:20242321 实验教师:王志强 实验日期:2025年3月25日 必修/选修: 公选课 一、实验内容熟悉Python开发环境; 练习Python运行、调试技能;(编写书中的…