CompletableFuture 处理异步异常

1、自定义线程池

@Configuration
public class ThreadPoolConfig {

    public static ThreadPoolExecutor getThreadPoolExecutor() {
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        return new ThreadPoolExecutor(
                availableProcessors,
                availableProcessors,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(9999),
                new ThreadFactoryBuilder().setNameFormat("custom-thread-pool-%d").build(),
                new ThreadPoolExecutor.CallerRunsPolicy());
    }

}

2、程序存在异常,却返回成功

写一个存在异常的程序,让其异步执行

public static final ThreadPoolExecutor CUSTOM_THREAD_POOL = ThreadPoolConfig.getThreadPoolExecutor();

/**
 * 异步执行异常测试
 */
@ApiOperation(value = "异步执行异常测试", code = 800)
@GetMapping("/asyncException")
public ResponseData<Object> asyncException() {
    try {
        try {
            CompletableFuture.runAsync(() -> {
                int i = 1 / 0;
            }, CUSTOM_THREAD_POOL);
        } catch (Exception e) {
            log.error("异常信息: " + e.getMessage(), e);
            throw new BusinessException(e.getMessage());
        }
        return new ResponseData<>(StatusCodeEnum.SUCCESS_CODE.getStatusCode(), "操作成功");
    } catch (Exception e) {
        return new ResponseData<>(StatusCodeEnum.ERROR_CODE.getStatusCode(), "操作失败:" + e.getMessage());
    }
}

结果:接口返回成功,控制台没有打印错误信息。
在这里插入图片描述

3、异步调用join()

// join方法获取异常信息: 将异步线程中发生的异常信息抛到主线程, 这样异常可被主线程捕获
try {
    CompletableFuture.runAsync(() -> {
        int i = 1 / 0;
    }, CUSTOM_THREAD_POOL).join();
} catch (Exception e) {
    log.error("外层异常信息: " + e.getMessage(), e);
    throw new BusinessException(e.getMessage());
}

结果:接口返回失败,控制台打印异常日志。
在这里插入图片描述

4、异步调用get()

异步方法中get()是阻塞的,在使用时要设置超时时间。

// get方法获取异常信息: 将异步线程中发生的异常信息抛到主线程, 这样异常可被主线程捕获
try {
    CompletableFuture.runAsync(() -> {
        int i = 1 / 0;
    }, CUSTOM_THREAD_POOL).get(2, TimeUnit.SECONDS);
} catch (Exception e) {
    log.error("外层异常信息: " + e.getMessage(), e);
    throw new BusinessException(e.getMessage());
}

结果:接口返回成功,控制台打印异常信息。
在这里插入图片描述

5、异步调用exception()

// exceptionally获取异常信息: 异常是存在于异步当中的, 不能被主线程捕获
try {
    CompletableFuture.runAsync(() -> {
        int i = 1 / 0;
    }, CUSTOM_THREAD_POOL)
    .exceptionally(e -> {
        log.error("异步运行异常信息: " + e.getMessage(), e);
        throw new BusinessException(e.getMessage());
    });
} catch (Exception e) {
    log.error("异常信息: " + e.getMessage(), e);
    throw new BusinessException(e.getMessage());
}

结果:接口返回成功,控制台打印异步线程异常日志,主线程没有打印异常日志
在这里插入图片描述

6、异步调用whenComplete()

// whenComplete获取异常信息: 异常是存在于异步当中的, 不能被主线程捕获
try {
    CompletableFuture.runAsync(() -> {
        int i = 1 / 0;
    }, CUSTOM_THREAD_POOL)
    .whenComplete((r, e) -> {
        if (e != null) {
            log.error("异步执行异常信息: " + e.getMessage(), e);
            throw new BusinessException(e.getMessage());
        }
    });
} catch (Exception e) {
    log.error("异常信息: " + e.getMessage(), e);
    throw new BusinessException(e.getMessage());
}

结果:结果返回成功,控制台打印异步线程异常信息,主线程没有打印异常信息
在这里插入图片描述

7、异步调用handle()

// handle获取异常信息: 异常是存在于异步当中的, 不能被主线程捕获
try {
    CompletableFuture.runAsync(() -> {
        int i = 1 / 0;
    }, CUSTOM_THREAD_POOL)
    .handle((r, e) -> {
        if (e != null) {
            log.error("异步执行异常信息: " + e.getMessage(), e);
            throw new BusinessException(e.getMessage());
        }
        return null;
    });
} catch (Exception e) {
    log.error("异常信息: " + e.getMessage(), e);
    throw new BusinessException(e.getMessage());
}

结果:结果返回成功,控制台打印异步线程异常信息,主线程没有打印异常信息
在这里插入图片描述

8、程序发生异常时需要做处理,可以调用get()/join()

try {
    CompletableFuture.runAsync(() -> {
        int i = 1 / 0;
    }, CUSTOM_THREAD_POOL)
    .exceptionally(e -> {
        log.error("异步执行异常信息: " + e.getMessage(), e);
        throw new BusinessException(e.getMessage());
    }).join();
} catch (Exception e) {
    log.error("异常信息: " + e.getMessage(), e);
    throw new BusinessException(e.getMessage());
}

try {
    CompletableFuture.runAsync(() -> {
        int i = 1 / 0;
    }, CUSTOM_THREAD_POOL)
    .exceptionally(e -> {
        log.error("异步执行异常信息: " + e.getMessage(), e);
        throw new BusinessException(e.getMessage());
    }).get(2, TimeUnit.SECONDS);
} catch (Exception e) {
    log.error("异常信息: " + e.getMessage(), e);
    throw new BusinessException(e.getMessage());
}

在这里插入图片描述

9、程序发生异常时不做处理直接报错,直接调用get()/join()

直接的异步方法后调用get()/join()。

10、总结

在使用异步CompletableFuture时,无论是否有返回值都要调用get()/join()方法,避免程序执行报错了,仍然返回成功。如果在程序报错时需要对上一个异步任务结果做其他操作,可以调用whenComplete()、handle()处理,如果只是对异常做处理,不涉及对上一个异步任务结果的情况,调用exceptionally()处理。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入探索:Zookeeper+消息队列(kafka)集群

目录 前言 一、Zookeeper概述 1、Zookeeper概念 2、Zookeeper 特点 3、Zookeeper工作机制 4、Zookeeper 选举机制 4.1 第一次启动选举机制 4.2 非第一次启动选举机制 5、Zookeeper 数据结构 6、Zookeeper 应用场景 二、部署 Zookeeper 集群 1、环境部署 2、安装 z…

Linux进阶篇:linux操作系统一个神奇的分区:swap交换分区

linux操作系统一个神奇的分区&#xff1a;swap交换分区 1 Swap交换分区概念 Linux内核为了提高读写效率与速度&#xff0c;会将文件在内存中进行缓存&#xff0c;这部分内存就是Cache Memory(缓存内存)。即使你的程序运行结束后&#xff0c;Cache Memory也不会自动释放。这就…

macOS 待机一段时间后所有打开的应用会被退出

最近在使用MacBook电脑时&#xff0c;发现电脑在待机一段时间再登录进去时&#xff0c;发现所有打开的应用都被退出了&#xff0c;就跟刚开机一样&#xff0c;很影响使用体验&#xff0c;查找资料时发现有个设置被打开了&#xff0c;只需关闭这个设置就可以解决该问题&#xff…

数据结构--选择排序

1、选择排序 1.1 基本认识 1.1.1 基本概念 选择排序是一种简单直观的排序算法&#xff0c;无论什么数据进去都是 O(n) 的时间复杂度。 1.1.2 算法步骤 &#xff08;1&#xff09;首先在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起…

Java并发--内存结构图及线程安全

内存结构图 内存-> (开辟的数组) -> (方法区&#xff0c;堆&#xff0c;栈&#xff0c;程序计数器&#xff0c;本地方法栈) 堆&#xff1a;几乎所有的对象实例都在这里分配内存。堆中每个对象的头信息都标属着他属于哪个类。 方法区它用于存储已被虚拟机加载的类型信息…

实现iOS App代码混淆

简介 在开发iOS应用程序时&#xff0c;保护代码安全是至关重要的。代码混淆是一种常用的技术&#xff0c;可以增加逆向工程的难度&#xff0c;防止他人对代码的篡改和盗用。本文将介绍如何实现iOS App代码混淆的步骤和操作方法。 整体流程 下面是实现iOS App代码混淆的整体流…

Python输入与输出

🥇作者简介:CSDN内容合伙人、新星计划第三季Python赛道Top1 🔥本文已收录于Python系列专栏: 零基础学Python 💬订阅专栏后可私信博主进入Python学习交流群,进群可领取Python视频教程以及Python相关电子书合集 私信未回可以加V:hacker0327 备注零基础学Python 订阅专…

浏览器渲染原理-解释回流重绘以及为什么transform效率高

浏览器是如何渲染页面 当浏览器的网络线程收到 HTML 文档后&#xff0c;会产生一个渲染任务&#xff0c;并将其传递给渲染主线程的消息队列。在事件循环机制的作用下&#xff0c;渲染主线程取出消息队列中的渲染任务&#xff0c;开启染流程。 整个渲染流程分为多个阶段&#xf…

HW面试经验分享 | 某服蓝队初级

前言 依稀记得是22年 7、8月份参加的HW&#xff0c;当时是比较炎热的时候&#xff0c;但又夹杂一丝秋意。也是头一次去离家乡比较远的地方&#xff0c;多少有点忐忑……&#xff08;怕被噶腰子、水土不服、吃穿用住没着落等等&#xff09;&#xff0c;但最终也是平安无事且顺利…

笔记84:关于递归法的一些感悟

题目1&#xff1a;二叉树的前序遍历 链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(…

独立服务器如何安装Webmin面板

本周有一个客户&#xff0c;购买Hostease的独立服务器&#xff0c;询问我们的在线客服&#xff0c;独立服务器支持安装Webmin及如何安装的问题。我们为用户提供教程&#xff0c;用户很快完成了设置。在此&#xff0c;我们分享这个操作教程&#xff0c;希望可以对您有帮助。 Web…

SkyWalking 为所有的API接口增加 tag

背景胡扯 线上接口报错&#xff0c;接着被 SkyWalking 抓到&#xff0c;然后 SkyWalking 触发告警&#xff0c;最后老板你&#xff0c;让你辛苦一下&#xff0c;在明早上班前把这个bug 改了&#xff0c;并告诉你你是全公司的希望。谁说不是呢&#xff1f;为公司业务保驾护航&a…

成都欣丰洪泰文化传媒有限公司领航电商新纪元

在当今数字化飞速发展的时代&#xff0c;电商行业异军突起&#xff0c;成为推动经济增长的重要力量。在这股浪潮中&#xff0c;成都欣丰洪泰文化传媒有限公司以其专业的电商服务脱颖而出&#xff0c;成为业界的佼佼者。本文将带您一探这家公司的独特魅力和专业服务&#xff0c;…

D365开发-在视图按钮的js里,引用别的js里的公共方法

公共方法写法&#xff1a; "use strict"; var JJMC window.JJMC || {}; JJMC.SamMCommon JJMC.SamMCommon || {}; (function () { this.cloneRecord function (excludeAttrbuteNames){ / } }).call(JJMC.SamMCommon); 然后在需要调方法的command里面&#xff0c;之…

手机适配,在真机上适配正常,在pc端适配出现横向滚动条

问题背景 最近&#xff0c;在做一个项目适配的时候&#xff0c;出现一个很奇怪的问题&#xff0c;在真机上&#xff0c;适配一切正常&#xff0c;但是在pc端&#xff0c;适配&#xff0c;偶现横向滚动条。 而且发现一个离奇的事情&#xff0c;就是适配出现横向滚动条&#xff…

UE5 GAS开发P32,33 初始化状态并绑定在HUD上,拾取物品增加血量和减少蓝量

这节课主要是修改WidgetController和OverlayController,在EffectActor内新增了一个减少蓝量的代码,同时修复了一个bug,并且展示了为什么要写成单独的控制器,因为要考虑多人游戏的情况,每一个控制器都是一个单独的角色 首先修改AuraAttirbuteSet.cpp UAuraAttributeSet::UAura…

泰山众筹:低门槛高回报的电商营销新模式

大家好&#xff0c;我是吴军&#xff0c;来自一家专注于软件开发的公司&#xff0c;担任产品经理一职。今天&#xff0c;我想与大家分享一种备受瞩目的商业模式——泰山众筹。 泰山众筹之所以能够在市场上迅速走红&#xff0c;其背后的原因值得我们深入探讨&#xff1a; 首先&…

ATFX港股:长周期看,恒生指数报价已经回到2008年以来的底部区域

消息面&#xff1a; 1、 4月12日&#xff0c;官方发布《推动资本市场高质量发展的若干意见》文件&#xff0c;其中提到九条意见&#xff0c;被称为“国九条”&#xff0c;重要内容有&#xff1a;将上市前突击“清仓式”分红等情形纳入发行上市负面清单&#xff1b;推动一年多次…

Vue3学习05 一些API

Vue3-API 其它 API【shallowRef 与 shallowReactive 】shallowRefshallowReactive总结 【readonly 与 shallowReadonly】readonlyshallowReadonly 【toRaw 与 markRaw】toRawmarkRaw 【customRef】 Vue3新组件【Teleport】【Suspense】【全局API转移到应用对象】【其他】 其它 …

罗芬COHERENT pmb激光电源维修HPC830

Rofin激光电源 PMB高压电源维修:HPC625,HPC520,HPC210,HPC840,HPC830,HPC810,HPC818,HPC818 HPC814 HPC910等型号。 大型设备往往都配有功能较为故障诊断程序&#xff0c;我们可以充分利用软件的提示&#xff0c;缩小故障排查范围&#xff0c;但有时诊断软件提示的受损元件是否…