CompletableFuture异步业务 默认ForkJoinPool 导致类加载器加载类失败

目录

1、Bug案发现场

2、捉虫过程过程

3、解决方案与代码

4、成果展现与总结 ​编辑

5、参考文章


1、Bug案发现场

        最近参与帮助以前同事实际业务开发中业务,在一个业务场景之中;使用H5页面通过二维码收集小微企业/个体工商户贷款业务需求。其中在获得用户输入企业名称后,获得企业或者个体工商户信用代码后,使用CompletableFuture的.supplyAsync方法实现异步保存企业基本信息到数据库之中;但是此异步操作类默认使用的ForkJoinPool 作为线程池。于是发生一个奇怪的Bug,在测试环境(test)【阿里云的ECS Docker JDK21+MySQL8.0.36+Redis 7.0.5】可以很正常实现数据保存;但是在正式环境部署到山东某市客户服务器上【Docker JDK21+Redis 7.0.5+MySQL5.7.44】死活无法保存基本公司信息到数据库里面。

具体出错问题就是下面这行代码

redisTemplate.boundValueOps(CACHE_KEY_PREFIX + key).get()

非法参数异常,未找到类对应的类。具体错误信息如下所示 :

+---[39.81% 0.872861ms ] vip.xiaonuo.common.cache.CommonCacheOperator:get() #203 [throws Exception]`---throw:java.lang.IllegalArgumentException #881 [org.springframework.data.redis.core.BoundValueOperations referenced from a method is not visible from class loader: 'app']  

2、捉虫过程过程

       我们在这个过程之中,怀疑过JDK21版本问题,退回到JDK17;怀疑过Redis问题也搭建相同的版本;所有的验证都是徒劳的。并且比较奇怪的Test环境一切正常。生产环境就是报错。从业务角度来说也是需要使用异步的方式来分开处理业务需求。甚至网上找到github上一篇类似文章。

https://github.com/spring-projects/spring-data-redis/issues/2772 【国内可能无法打开 上有截图】

        最后思考后继续寻找异常关键词语

throw:java.lang.IllegalArgumentException #881 [org.springframework.data.redis.core.BoundValueOperations referenced from a method is not visible from class loader

        于是SegmentFault 思否 网站上找一篇类似文章,有相关异常描述。最后定位并确定就是因为以前使用 CompletableFuture.supplyAsync() 异步方法,默认使用的 ForkJoinPool 作为线程池所导致的。

       在有上述思路后,今天去开发现场,使用自己定义线程池;替换了默认ForkJoinPool线程池;时间这个困扰1周左右的问题。并且实现了基本公司信息正确正常入库。

3、解决方案与代码

    自定义线程池

@Configuration
public class ThreadPoolConfig {// 核心线程数private int corePoolSize = 5;// 最大线程数private int maxPoolSize = 10;// 队列大小private int queueSize = 40;// 线程最大空闲时间private int keepAliveSeconds = 40;/*** 自定义消费队列线程池* CallerRunsPolicy 这个策略重试添加当前的任务,他会自动重复调用 execute() 方法,直到成功。* AbortPolicy 对拒绝任务抛弃处理,并且抛出异常。* DiscardPolicy 对拒绝任务直接无声抛弃,没有异常信息。* DiscardOldestPolicy 对拒绝任务不抛弃,而是抛弃队列里面等待最久的一个线程,然后把拒绝任务加到队列。* @return*/@Bean(value = "customAsyncTaskThreadPool")public ThreadPoolTaskExecutor buildCustomAsyncTaskThreadPool() {ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();threadPool.setCorePoolSize(corePoolSize);threadPool.setMaxPoolSize(maxPoolSize);threadPool.setQueueCapacity(queueSize);threadPool.setThreadNamePrefix("customAsyncTaskThreadPool-");threadPool.setKeepAliveSeconds(keepAliveSeconds);threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//如果@Bean 就不需手动,会自动InitializingBean的afterPropertiesSet来调initialize//threadPool.initialize();return threadPool;}
@Resource
@Qualifier("customAsyncTaskThreadPool")
private Executor asyncTaskThreadPoolExecutor;private void saveCompanyBasicInfo(CompanyLoanDemandCreateParam companyLoanDemandCreateParam) {CompletableFuture.supplyAsync(() -> {try {String uscc = companyLoanDemandCreateParam.getUscc();String key = String.format(BusinessConstant.WE_COMPANY_CACHE_KEY, uscc);log.error("key  "+key);Object data =null;try {data =commonCacheOperator.get(key);} catch (Exception e) {log.error(e.toString());}if (ObjectUtils.isEmpty(data)) {//处理业务内容}} catch (ParseException e) {log.error("saveCompanyBasicInfo error", e);}return null;},asyncTaskThreadPoolExecutor);

4、成果展现与总结 

        通过解决困扰我同事与我这个问题;让我明白一个道理,如同最近在看《毛选--->实践论与矛盾论》要解决实际问题只有深入实践并且注意矛盾的特殊性;因为每个开发场景可能与网上文章有相似【矛盾的普遍性】但是又有其自己开发与运行环境的【特殊性】;只有抓住特殊性并结合普遍性才能够找到解决问题的主要矛盾;并使得获得有效的方法论去解决实际问题。

5、参考文章

      ForkJoinPool 导致类加载器加载类失败

     springboot自定义线程池,CompletableFuture实现多线程并发

    生产问题之CompletableFuture默认线程池踩坑,请务必自定义线程池

    CompletableFuture使用自定义线程池实现多任务结果聚合返回 

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

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

相关文章

mybatis-plus超详细讲解

mybatis-plus (简化代码神器) 地址:https://mp.baomidou.com/ 目录 mybatis-plus 简介 特性 支持数据库 参与贡献 快速指南 1、创建数据库 mybatis_plus 2、导入相关的依赖 3、创建对应的文件夹 4、编写配置文件 5、编写代码 …

Houdini abc 导入 maya uv无法识别

参考:Houdini导出abc 至maya UV 无法识别_houdini导出abc没有uv-CSDN博客 从maya导入到houdini的uv默认是vertex层级的,而在maya中,uv是在point层级的;因此在houdini中导出abc时应将uv转为点层级,使用vertexsplit节点&…

2025erp系统开源免费进销存系统搭建教程/功能介绍/上线即可运营软件平台源码

系统介绍 基于ThinkPHP与LayUI构建的全方位进销存解决方案 本系统集成了采购、销售、零售、多仓库管理、财务管理等核心功能模块,旨在为企业提供一站式进销存管理体验。借助详尽的报表分析和灵活的设置选项,企业可实现精细化管理,提升运营效…

半导体数据分析(二):徒手玩转STDF格式文件 -- 码农切入半导体系列

一、概述 在上一篇文章中,我们一起学习了STDF格式的文件,知道了这是半导体测试数据的标准格式文件。也解释了为什么码农掌握了STDF文件之后,好比掌握了切入半导体行业的金钥匙。 从今天开始,我们一起来一步步地学习如何解构、熟…

OCR:文字识别

使用场景: 远程身份认证 自动识别录入用户身份/企业资质信息,应用于金融、政务、保险、电商、直播等场景,对用户、商家、主播进行实名身份认证,有效降低用户输入成本,控制业务风险 文档电子化 识别提取各类办公文档、合同文件、企…

深入C语言文件操作:从库函数到系统调用

引言 文件操作是编程中不可或缺的一部分,尤其在C语言中,文件操作不仅是处理数据的基本手段,也是连接程序与外部世界的重要桥梁。C语言提供了丰富的库函数来处理文件,如 fopen、fclose、fread、fwrite 等。然而,这些库…

linux上qt打包(二)

sudo apt install git 新建一个文件夹 名为xiazai, chmod -R 777 xiazai cd xiazai 并进入这个文件夹,然后clone git clone https://github.com/probonopd/linuxdeployqt.git 此处可能要fanQiang才能下 cd linuxdeployqt文件夹 下载平台需要的…

Windos中解决redis-server.exe闪退问题

一、闪退原因 (一)数据状态异常 数据不一致 在 Redis 运行过程中,如果发生意外情况,如突然断电、系统崩溃或者不正确的操作,可能会导致数据在内存中的存储状态不一致。例如,Redis 使用多种数据结构&#x…

【数据分享】2013-2023年我国省市县三级的逐年CO数据(免费获取\excel\shp格式)

空气质量数据是在我们日常研究中经常使用的数据!之前我们给大家分享了2000-2023年的省市县三级的逐年PM2.5数据、2000-2023年的省市县三级的逐年PM10数据、2013-2023年的省市县三级的逐年SO2数据、2000-2023年省市县三级的逐年O3数据和2008-2023年我国省市县三级的逐…

华为WLAN基础配置(AC6005模拟配置)

AC6005基础配置 本次实验模拟华为AC6005的基本配置 Tip display interface GigabitEthernet 0/0/0 查看ap接口mac 前提条件&#xff1a;Vlan10为业务网段&#xff0c;vlan100为管理网段&#xff0c;5700作为dhcp。 5700配置如下 <Huawei>sy [Huawei]sys 5700 //设…

shell编程2 永久环境变量和字符串显位

声明 学习视频来自B站UP主 泷羽sec 常见变量 echo $HOME &#xff08;家目录 root用户&#xff09; /root cd /root windows的环境变量可以去设置里去新建 为什么输入ls dir的命令的时候就会输出相应的内容呢 因为这些命令都有相应的变量 which ls 通过这个命令查看ls命令脚本…

WebRTC服务质量(05)- 重传机制(02) NACK判断丢包

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…

AI工具如何深刻改变我们的工作与生活

在当今这个科技日新月异的时代&#xff0c;人工智能&#xff08;AI&#xff09;已经从科幻小说中的概念变成了我们日常生活中不可或缺的一部分。从智能家居到自动驾驶汽车&#xff0c;从医疗诊断到金融服务&#xff0c;AI正以惊人的速度重塑着我们的世界。 一、工作方式的革新…

基于matlab的单目相机标定

链接&#xff1a; 单目相机标定&#xff08;使用Matlab&#xff09; 用Matlab对单目相机参数的标定步骤&#xff08;保姆级教程&#xff09; 1.准备代码 调用摄像头代码&#xff08;用于测试摄像头是否可用&#xff09;&#xff1a; #https://blog.csdn.net/qq_37759113/art…

[maven]使用spring

为了更好理解springboot&#xff0c;我们先通过学习spring了解其底层。 这里讲一下简单的maven使用spring框架入门使用。因为这一块的东西很多都需要联合起来后才好去细讲&#xff0c;本篇通过spring-context大致地介绍相关内容。 注意&#xff1a;spring只是一个框架&#xff…

eBay如何养号?新手养号宝典

​ebay是热门的跨境电商平台之一&#xff0c;然而与其他跨境电商平台不同&#xff0c;不同等级的ebay账户可刊登的数量是不同的。对于新手来说&#xff0c;想要提升ebay账户的等级就需要养号。那ebay如何养号&#xff1f;本文将带来一些实用的养号策略&#xff0c;帮助新手快速…

学习日志024--opencv中处理轮廓的函数

目录 前言​​​​​​​ 一、 梯度处理的sobel算子函数 功能 参数 返回值 代码演示 二、梯度处理拉普拉斯算子 功能 参数 返回值 代码演示 三、Canny算子 功能 参数 返回值 代码演示 四、findContours函数与drawContours函数 功能 参数 返回值 代码演示 …

梳理你的思路(从OOP到架构设计)_UML应用:业务内涵的分析抽象表达03

目录 1、举例(四)&#xff1a;五子棋 【五子棋】 的分析步骤 2、讨论&#xff1a; 模型与代码 1、举例(四)&#xff1a;五子棋 【五子棋】 的分析步骤 Step-1: 找到主角— 棋手&#xff0c;很容易发现核心的概念了&#xff0c;例如&#xff1a;五子棋游戏的主角是棋手(玩家…

人员离岗监测摄像机智能人员睡岗、逃岗监测 Python 语言结合 OpenCV

在安全生产领域&#xff0c;人员的在岗状态直接关系到生产流程的顺利进行和工作环境的安全稳定。人员离岗监测摄像机的出现&#xff0c;为智能人员睡岗、逃岗监测提供了高效精准的解决方案&#xff0c;而其中的核心技术如AI识别睡岗脱岗以及相关的算法盒子和常见的安全生产AI算…

【计算机网络】Layer4-Transport layer

目录 传输层协议How demultiplexing works in transport layer&#xff08;传输层如何进行分用&#xff09;分用&#xff08;Demultiplexing&#xff09;的定义&#xff1a;TCP/UDP段格式&#xff1a; UDPUDP的特点&#xff1a;UDP Format端口号Trivial File Transfer Protocol…