全局共用一个线程池竟然发生死锁了

news2024/9/21 2:40:48

在我们进行代码开发时,我也见过很多全局注册一个自定义线程池(也有可能不是自定义的,直接使用更不推荐Executors 创建的线程池),也许是业务量不高、也许是其他原因,反正全局可这一个线程池使劲造。

先给大家看一段代码,也欢迎你在评论区留下你的看法!

一、看个代码

  • 业务逻辑代码

  • 图片

  • 自定义线程池 BizThreadPool 代码如下

  • 图片

通过上方的代码示例,如果你还没有看出问题,那你可以停留几秒思考一下。

自定义线程池创建,使用的这个队列,嗯......,大家工作中一定不要这么用,此处只是为了做演示使用。

如果你已经看出来了问题所在,也希望你能继续看下去,验证一下咱们是不是想的相同。

图片

二、有啥问题

经过短暂几秒钟的思考之后,决定还是运行一下 Demo 看看现象。

封装一个 controller 直接启动 Springboot 程序,Java 启动。

图片

启动成功之后调用 GET http://localhost:8080/test/test,输出结果如下。

图片

按照我们的预期,日志中应该也要输出子任务才对啊,怎么创建的子任务没有输出呢,看现象应该是没有执行。

那我们先执行一下 jstack 命令看一下线程相关的信息,输出信息中其中一段如下所示。

图片

通过上面的堆栈信息可以看出,主线程在将父任务执行完成之后,开启了一个CountDownLatch并等待3个子任务执行完成。

问题就在这,一直等待,一直等不到结果,所以就是我们刚开始看到的结果,只有父任务执行了,子任务并没有执行。

一次调用没有响应,多次调用之后,达到服务器资源瓶颈时系统就该发生崩溃了。

那么子任务为何没有执行到呢?

三、小试牛刀

首先我们从头开始捋一下,先看下线程池的配置。

图片

我们在创建自定义线程池时,核心线程与最大线程都设置的1,那我们直接修改最大线程数量,让线程池有线程可以执行子任务不就行了吗?

对于生产中,核心线程与最大线程一般也不会设置为1,但是哪怕你设置为101001000,极端情况下也会出现本文后面将要讲述的问题。

说干就干,创建自定义线程池的代码变为了如下形式。

图片

非常自信的你重启程序,然后调用接口,最终傻眼了,怎么没变化?

如果你修改完最大线程数就去重启程序的话,说明线程池的工作原理你已经忘了!

好吧原谅你了,这次不准再忘了,下面跟我一起来看看这究竟是什么原因。

四、线程池工作流程

这里放一下线程池的工作流程。

面试官:线程池核心线程设置为0时任务执行流程怎么样的

图片

图片

知道了线程池的工作流程之后,在上述代码中,哪怕增加了最大线程池的数量,最终子任务也并不会执行到,我们可以打印一下当前线程池的状态进行辅助观察。(上述代码的printThreadPoolStatus()方法会进行线程池当前状态的打印)

调用一下GET http://localhost:8080/test/info方法查看线程池当前的状态。

图片

可以看到队列中存在3个任务在排队,等待线程池分配线程执行任务。这也就是修改了最大线程池数量未生效的原因,因为还有一个无界队列

当然如果任务一直增加,队列中任务数量越来越多,达到服务器的瓶颈,就会发生OOM了。(阿里开发规范中不推荐使用无界队列的原因

五、修改核心线程数量

那我们直接修改核心线程数量吧,核心线程超过任务数量?

回答:不行。

图片

对于我们上面的例子来说,增加核心线程数量,拥有可以执行子任务的线程,确实可以解决当下场景。

但是当并发量上来之后,或者说线程池的线程都被父线程所占用时,依旧会发现子任务无法获得线程执行。

此处我们修改核心线程为10执行看一下输出结果。

图片

通过修改核心线程数量,解决了子任务在队列中堆积的问题。

所以通过上述代码,大家应该知道死锁是怎么发生的了吧,这里我总结一下。

六、小结

  • 当核心线程为1,最大线程为1,使用无界队列

    父任务在线程中等待子任务完成的通知,子任务在线程池的任务队列中等待线程池调度线程资源。

  • 图片

  • 当核心线程为1,最大线程为n,使用无界队列

    最大线程设置n与设置1没有区别,除非使用的队列不同,只要是使用的无界队列,当资源耗尽之时,就是服务崩溃的时候。

    此时后面新的父任务到来时,也只会在任务队列中继续堆积。

  • 图片

  • 当核心线程为n,最大线程为n,使用无界队列

    核心线程设置为n,意味着父线程大概率是可以执行的,创建的子任务在任务队列中排队执行。

  • 图片

  • 当并发量上来,或者核心线程都被父任务所占据之后,线程池调用就变成了如下场景,所有的任务都被堆积在任务队列当中

  • 图片

  • 核心线程全是父任务,后面创建的任务也都在任务队列堆积,最终达到服务器瓶颈系统OOM

七、最终解决方案

通过上述代码示例,死锁的根本原因在于,父任务会创建多个子任务,并等待子任务执行结束,而父子任务都是使用的同一个线程池,当线程池中执行线程都是父任务时,所有的子任务又都在任务队列中等待执行,所以这样就会发生死锁。

核心线程永远不会释放,从而造成任务队列不断堆积,直到OOM

图片

所以解决方案就是,隔离线程池

不同的业务使用不同的线程池,使用一个新的线程池处理子任务,这样就可以避免死锁的发生了。

修改之后的代码如下。

图片

通过查看日志输出可以发现,线程池隔离之后,哪怕核心线程设置为1,也是可以正常执行业务逻辑的,任务队列中也没有堆积任务。

八、总结

通过上面的 Demo 复现以及解决方案,在工作中优化建议如下。

1、禁止使用Executors创建自定义线程池。使用ThreadPoolExecutor创建线程池时,注意每个参数的含义,规避资源耗尽的风险。

2、线程池使用有界队列,避免使用无界队列。

3、对于父子任务的场景,可以使用线程池或者 MQ。使用有界队列之后,制定合理的拒绝策略,拒绝策略可以考虑 MQ 做重试。

4、不同业务使用不同的线程池,禁止父子任务使用相同的线程池。

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

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

相关文章

深入FastAPI:掌握使用多个关联模型的高级用法[Union类型]

在FastAPI中,响应模型可以声明为Union类型,这允许你为同一个端点定义多种可能的响应模型。这种灵活性使得API可以根据不同的情况返回不同类型的数据结构。 例如,根据请求中的查询参数或数据库中的数据,一个API端点可能有时返回一…

零信任安全:重新思考数字世界的访问

目录 ​编辑 网络安全形势的演变 数字安全的变化 引入零信任安全 零信任的当今意义 了解零信任原则 零信任架构的核心概念 实施微分段 持续验证:积极主动的立场 与传统安全模型的对比 在现代企业中实施零信任 零信任实施基础知识 多重身份验证 (MFA) 的…

【数据结构】——二叉树(JAVA)

一、二叉树的定义二、二叉树的形态三、二叉树的性质四、二叉树的存储五、二叉树的创建与遍历(递归) 一、二叉树的定义 二叉树(Binary Tree) 是由n个结点构成的有限集(n≥0),n0时为空树,n>0时为非空树。对于非空树root&#xf…

如何在Linux 上运行 SciChart WPF图表控件?

SciChart – 一个跨平台图表库,可实现 Windows Presentation Foundation (WPF)、JavaScript 以及原生 iOS (Swift/Objective-C) 和 Android (Java/Kotlin),基于代号为 Visual Xccelerator 的专有 C 渲染引擎。这提供了 SciChart 众所周知的速度和性能&am…

网络编程项目(速递项目)

目录 一、功能要求 服务器 用户客户端 快递员客户端 二、演示效果 1.注册,登录,注销功能演示 ​编辑 2.用户功能演示 ​编辑 3.快递员功能演示 三、项目代码 1.头文件: 2.服务器: 3.用户端: 4..快递员端&…

Vue2 day-04

目录 一. vue组件 1.1 为什么用组件 1.2 vue组件 1.3 基础使用 1.4 全局 - 注册使用 1.5 局部 - 注册使用 1.4 用less写的样式 二. Vue组件之间传值(重点) 2.1 父组件向子组件传值 2.2 子组件向父组件传值 2.3 兄弟之间的传递 三. vue生命周期 3.1 含义 3.2 钩子…

SprinBoot+Vue智慧农业专家远程指导系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质…

Transformer、RNN和SSM的相似性探究:揭示看似不相关的LLM架构之间的联系

通过探索看似不相关的大语言模型(LLM)架构之间的潜在联系,我们可能为促进不同模型间的思想交流和提高整体效率开辟新的途径。 尽管Mamba等线性循环神经网络(RNN)和状态空间模型(SSM)近来备受关注,Transformer架构仍然是LLM的主要支柱。这种格局可能即将发生变化:像Jamba、Samb…

红队C2工具Sliver探究与免杀

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330&scene21#wechat_redirect 《网安面试指南》…

【QCA(定性比较分析)组态研究】01 基础入门

【目录】 1.理论入门1.1和个案分析的区别1.2 QCA的特点因果非对称:殊途同归:1.3 什么时候用到QCA2.QCA的一般步骤3.QCA论文精读1.理论入门 QCA(定性比较分析)是一种探索性研究方法,旨在通过系统地比较不同案例的条件组合,识别出影响结果的因果关系。它结合了定性和定量分…

HarmonyOS Next系列之实现一个左右露出中间大两边小带缩放动画的轮播图(十二)

系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现(一) HarmonyOS Next 系列之验证码输入组件实现(二) HarmonyOS Next 系列之底部标签栏TabBar实现(三) HarmonyOS Next 系列之HTTP请求封装和Token…

ASP.NET Core 中间件

一、什么是中间件? 中间件 是一种装配到 ASP.NET Core 应用程序请求处理管道中的软件组件,用于处理 HTTP 请求和响应。 每个中间件组件可以: 选择是否将请求传递到下一个中间件:通过调用 next() 或者不调用 next() 来决定是否将…

HTML5中的数据存储sessionStorage、localStorage

第8章 HTML5中的数据存储 之前通常使用Cookie存储机制将数据保存在用户的客户端。 H5增加了两种全新的数据存储方式:Web Stroage和Web SQL Database. 前者用于临时或永久保存客户端少量数据,后者是客户端本地化的一套数据库系统。 8.1 Web Storage存…

日本“大米荒”持续!政府再次拒绝投放储备米

KlipC报道:日本多地从7月开始出现“大米荒”,有部分新米上市,但是许多超市的大米仍然存在断购或限购的情况,并且部分新米价格上涨至去年同期的两倍。大阪府官员再次呼吁日本中央政府尽快投放储备米以缓解供应紧张,但遭…

Dynamics CRM Ribbon Workbench-the solution contains non-entity components

今天在一个低版本的环境里准备用Ribbon Workbench去编辑一个按钮时,遇到了如下错误 一开始没当回事,以为是我的解决方案问题,去检查了下,只有一个组件,并且哪怕我把组件换成了某个实体也不行,尝试了其他任何…

开源NAS系统-OpenMediaVault(OMV)共享存储网盘搭建和使用(保姆级教程)

1、OpenMediaVault简介 OpenMediaVault,简称:OMV,是由原 FreeNAS 核心开发成员 Volker Theile 发起的基于 Debian Linux 的开源 NAS 操作系统,主要面向家庭用户和小型办公环境。 OpenMediaVault是一款基于Debian Linux的开源网络附加存储(NAS)操作系统,它提供了强大的存…

酒店智能轻触开关:智慧化的创新实践

在追求高品质住宿体验的今天,酒店智能轻触开关作为智慧酒店建设的关键一环,正逐步成为提升酒店服务品质、优化运营效率、增强顾客满意度的有力工具。本文将深入探讨酒店智能轻触开关如何助力酒店实现智慧化管理,以及它所带来的多重变革。 一、…

大模型时代下,nlp初学者需要怎么入门?

前言 自从 ChatGPT 横空出世以来,自然语言处理(Natural Language Processing,NLP)研究领域就出现了一种消极的声音,认为大模型技术导致 NLP “死了”。 有人认为 NLP 的市场肯定有,但 NLP 的研究会遇到麻…

图片产生3D模型

HyperHuman 上传图片,点击生成 可以多生成几次,点击应用 让效果再好一点 生成完成之后可以导出为fbx格式

实战|等保2.0 Oracle数据库测评过程

以下等保测评过程以Oracle 11g为例,通过PL/SQL进行管理,未进行任何配置、按照等保2.0标准,2021报告模板,三级系统要求进行测评。 一、身份鉴别 a) 应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,…