Java并发编程—线程池参数配置、线程池配置、线程池监控

2023-11-05

一、线程池的参数配置

在这里插入图片描述

1.corePoolSize核心线程数选择

配置线程数量之前,首先要看任务的类型是 IO密集型,还是CPU密集型?
什么是IO密集型?比如:频繁读取磁盘上的数据,或者需要通过网络远程调用接口。
什么是CPU密集型?比如:非常复杂的调用,循环次数很多,或者递归调用层次很深等。
IO密集型配置线程数经验值是:2N,其中N代表CPU核数。
CPU密集型配置线程数经验值是:N + 1,其中N代表CPU核数。

如何获取CPU核数?

int availableProcessors = Runtime.getRuntime().availableProcessors();

2.workQueue工作队列(阻塞队列)选择

线程池中常用的阻塞队列有三种

BlockingQueue<Runnable> workQueue = null;
workQueue = new SynchronousQueue<>();//无缓冲的等待队列
workQueue = new ArrayBlockingQueue<>(5);//基于数组的先进先出队列
workQueue = new LinkedBlockingQueue<>();//基于链表的先进先出队列

如何选择?看看三者的区别

SynchronousQueue是一个不存储元素的阻塞队列,适合传递性场景,只是负责把父线程提交的任务直接交给线程池线程处理。也就是说提交的任务数超过最大线程数就会执行拒绝策略

ArrayBlockingQueue底层是用数组实现的有界阻塞队列,因为需要传初始值(如果传Integer最大值,也类似于无界了)。队列按照先进先出的原则对元素进行排序

LinkedBlockingQueue底层是用链表实现的有界阻塞队列,如果不传初始化值为Integer最大值,也是先进先出对元素进行排序

一般选择建议选择有界队列,因为如果任务特别多,核心线程处理不过来,会将任务都放到工作队列中,此时最大线程数已经没有意义了。如果控制不好会导致OOM

那么ArrayBlockingQueue和LikendBlockingQueue选择哪一个?

从底层实现来看LikendBlockingQueue需要维护一个个Node对象,需要额外的内存消耗。并且在生产和消费的时候,需要创建Node对象进行插入或移除,大批量数据的系统中,其对于GC的压力会比较大。

ArrayBlockingQueue只是维护final Object[] items;一个数组。在生产和消费的时候,是按照索引对数据插入或移除的,不会产生或销毁任何额外的对象实例

综合来说,可以选择ArrayBlockingQueue。

3.阻塞队列长度和最大线程数选择

这个问题网上大多回答是根据项目配置、响应时间要求来判断,或者根据公式计算。我觉得还是要根据具体项目来选择,比如可能要求在一定的响应时间内完成需求。

拿具体项目举例吧
项目需求

1.从项目中将客户数据导出pdf,然后压缩,下载下来
2.使用线程池子线程导出每个客户的pdf,压缩使用主线程
3.每个客户导出pdf的时间大概在1.5s左右,一组客户平均在60人,最大在150人
4.响应时间要在3s内完成

那么阻塞队列长度和最大线程数应该怎么设置?
因为响应时间在3s内,每一个pdf生成需要1.5s,那么可以将一组客户分为两组执行,一半放到阻塞队列,一半直接创建非核心线程执行。按组数人最大的进行分组,那么最大线程数和阻塞队列数对半分。还需要考虑主线程执行时间,那么可以设置非核心线程数大一点。推导的最后结果就是最大线程数可以设置成100,阻塞队列长度也可以设置成100。记得一定要回收非核心线程,配置keepAlivedTime。

4.拒绝策略选择

JDK提供了四种拒绝策略

  • AbortPolicy:直接丢弃新任务,抛出异常
  • DiscardPolicy:直接丢弃掉,不会抛出异常
  • DiscardOldestPolicy:丢弃时间最久的任务。一般是队列最前面的任务
  • CallerRunsPolicy:交给主线程去执行

当然也可以自定义拒绝策略,如果你的任务不能被拒绝的话,可以让任务重回队列,重新执行或者交给主线程执行。在下面例子中会写到。

二、SpringBoot环境下配置线程池

1.线程池配置

一般在Spring环境下,我们可以将ThreadPoolExecutor作为一个Bean交给Spring管理。配置如下

//1.yml文件配置
demo:
  thread:
    coreSize: 8
    maxSize: 100
    keepAliveTime: 60
    queueLength: 100

//2.读取yml文件配置
@ConfigurationProperties(prefix = "demo.thread")
@Data
public class ThreadPoolConfigProperties {

    private Integer coreSize;

    private Integer maxSize;

    private Integer keepAliveTime;

    private Integer queueLength;

}

//3.配置ThreadPoolExector的bean
@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {

    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool){
        return new ThreadPoolExecutor(
                pool.getCoreSize(),
                pool.getMaxSize(),
                pool.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(pool.getQueueLength()),
                Executors.defaultThreadFactory(),
                new RejectedExecutionHandler() {
                    @SneakyThrows
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        while (executor.getQueue().offer(r,5,TimeUnit.SECONDS)){
                            break;
                        }
                    }
                }
        );
    }
}

//4.使用,直接测试即可
 @Autowired
 private ThreadPoolExecutor executor;

 @RequestMapping("/threadtest")
 public void test(){
     for (int i = 0;i<100;i++){
         executor.execute(()->{
             System.out.println("sdf");
         });
     }
 }

学习下两个注解
@ConfigurationProperties和@EnableConfigurationProperties。两者的关系简单点说就是@EnableConfigurationProperties让@ConfigurationProperties注解的类的生效,并且将@ConfigurationProperties注解的bean信息作为spring的环境bean,可以直接取出数据
在这里插入图片描述

2.线程池的监控

线程池让线程得以复用、得以管理,但是线程池一旦使用不当可能会造成服务宕机、内存溢出等问题,所以我们可以监控下线程池。线程池提供一些方法可以获取相关的信息
在这里插入图片描述
拿到这些信息有什么用呢?还记得之前的SpringBoot Actuator吗,可以通过该机制将线程池的运行状态暴露出去,通过prometheus采集然后展示就可以了。


参考文章:
常见的8种拒绝策略:https://zhuanlan.zhihu.com/p/142254564
线程池企业级应用:https://blog.csdn.net/AlbenXie/article/details/105292727

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java并发编程—线程池参数配置、线程池配置、线程池监控 的相关文章

  • Hibernate 自定义架构创建

  • 谁能解释一下 servlet 映射吗?

    我正在尝试使用 SpringMVC 编写一个 Web 应用程序 通常我只是将一些虚构的文件扩展名映射到 Spring 的前端控制器并快乐地生活 但这次我要使用类似 REST 的 URL 没有文件扩展名 将我的上下文路径下的所有内容映射到前端
  • Jackson Json 将对象反序列化为列表

    我正在使用 Spring 的 Web 服务RestTemplate并反序列化Jackson 在来自服务器的 JSON 响应中 其中一个字段可以是对象或列表 这意味着它可以是 result or result 有没有办法通过对我要反序列化的类
  • 包含小时、分钟和秒的周期[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我需要一个代表年 月 周 日 小时 分钟 秒的间隔数据类型 前三年 年 月 日 可以用Period最后
  • 按对象值分组,统计后按最大对象属性设置组键

    我设法使用 Java 8 Streams API 编写了一个解决方案 该解决方案首先按对象 Route 的值对列表进行分组 然后计算每组中的对象数量 它返回一个映射 Route gt Long 这是代码 Map
  • 为什么 MetaSpace 大小是已用 MetaSpace 的两倍?

    我写了一个程序来模拟MetaSpace OOM 但我发现MetaSpace Size几乎总是两倍大Used MetaSpace Why 我用标志运行我的程序 XX MaxMetaspaceSize 50m 程序抛出OOM时Used Meta
  • 无法启动组件 [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/LabWebServletHibernate]]

    当使用 eclipse neon 1 在 tomcat 8 上运行应用程序时 我收到此错误 它使用 spring 4 3 3 hibernate 5 2 4 和 maven 嚴重 A child container failed durin
  • 文件保存在文件系统中 VS 保存在数据库中

    我正在设计一个 servlet 或 Struts2 中的操作 用于文件 图像 文档等 下载 但我想知道哪种更好的方法可以将文件保留在文件系统和数据库中 只需保留文件的路径或将文件保留在数据库中 如 BLOB 我知道当我查询数据库时 哪里的
  • (Java) 在 Mac OS X 上以编程方式访问“系统根目录”下的 SSL 证书

    我正在编写一个 Java 应用程序 它可以通过远程 Https 站点进行 REST Api 调用 远程站点由受信任的证书签名 它在 Windows 上运行良好 但由于 SSL 证书问题 在 OS X 上运行时遇到问题 我做了一些挖掘 发现原
  • 在 javafx 中注册鼠标处理程序,但处理程序不是内联的

    我有一个 JavaFX 应用程序变得有点大 我想保持代码的可读性 我有一个折线图 我希望内置缩放功能 该功能在单击鼠标时发生 我知道我需要向图表注册鼠标侦听器 我无法从 Oracle 示例中弄清楚什么 即如下所示 http docs ora
  • 在 JSON 对象中强制执行非空字段

    我们的 REST API 接收一些 JSON 对象输入 其中某些字段要求不为空 这些可以是字符串 整数 甚至可以是其他一些类实例作为参考 我们正在尝试找到一种方法来强制这些字段不为空 而不是在 API 中进行空检查的正确方法 当前的 if
  • 如何将 currentTimeMillis 转换为可读的日期格式? [复制]

    这个问题在这里已经有答案了 我想用currentTimeMillis两次 这样我就可以计算持续时间 但我也想以用户可读的格式显示时间和日期 我遇到了麻烦currentTimeMillis有利于计算 但我看不到内置函数可以转换为合适的时间或时
  • Java 中意外的负数

    import java util public class Prac9FibonacciNumbers public static void main String args int x new int 100 x 0 1 x 1 1 fo
  • 如何使用 UUID 生成唯一的正 Long

    我需要为我的数据库主键列生成唯一的长 ID 我以为我可以用UUID randomUUID getMostSignificantBits 但有时它也会产生一些负多头 这对我来说是个问题 是否可以从 UUID 中仅生成正长 将会有数十亿个条目
  • 如何在Webview中保存用户名和密码

    目前 我还在学习Android开发的过程中 所以如果我的这个问题对你来说不太容易理解 请原谅 我创建了一个 Android 应用程序 它使用 RecyclerView 显示一组列表 当用户单击列表中的每个名称时 它会将它们重定向到一组不同的
  • Android - 保持用户登录状态

    我正在尝试使用 PHP 和 MySQLi for Android 进行登录 我不明白的是如何保持用户登录状态 我看到一个简单的教程 其中有人使用 SQLite 来保护信息 但我不知道这是否真的安全 如何保存用户信息以保持用户登录状态 谢谢
  • 线程睡眠阻止我的 Swing 应用程序执行

    我的应用程序发生的事情是有道理的 但我不知道如何修复它 以下是我的应用程序功能的简要描述 计时器窗口应显示在屏幕右下角并显示实时时间 一小时后 它应该执行一些操作 我还没有决定该操作 我面临的问题是定时器 java当我刷新实时计时器的秒数时
  • 如何将多部分文件从另一个服务发送到一个服务

    我有两个端点 api 它们是 uploadand 重定向 upload是我直接上传文件的地方 重定向是我接收文件并将其传递给上传并获取 JSON 响应的地方 upload 所以下面是我的代码 package com example impo
  • RecyclerView 适配器的 Kotlin 泛型

    我正在尝试编写一个通用的 recyclerview 适配器 我找到了几个例子 然而 仍然无法弄清楚如何实现通用适配器 我写的代码是 open abstract class BaseAdapter
  • 根据 Java 环境变量中的值创建使用 @JsonIgnore 的自定义注释

    我需要创建一个新的注释 用于在环境变量设置时忽略输出 JSON 文件中的字段var false 我尝试使用JsonAnnotationIntrospector 但无法获得预期的输出 public class Vehicle String v

随机推荐

  • 拓端tecdat

    最近我们被要求撰写关于ARIMA ARCH的研究报告 包括一些图形和统计输出 时间序列分析模型 ARIMA ARCH GARCH模型分析股票价格数据 相关视频 在Python和R语言中建立EWMA ARIMA模型预测时间序列 简介 时间序列
  • 初学者的卡尔曼滤波——扩展卡尔曼滤波(一)

    简介 已经历经了半个世纪的卡尔曼滤波至今仍然是研究的热点 相关的文章不断被发表 其中许多文章是关于卡尔曼滤波器的新应用 但也不乏改善和扩展滤波器算法的研究 而对算法的研究多着重于将卡尔曼滤波应用于非线性系统 为什么学界要这么热衷于将卡尔曼滤
  • 文化的特点计算机,计算机文化基础 计算机的特点与分类 计算机特点与分类.pptx...

    1 4 3计算机的特点和分类 精确性高 计算机的可靠性很高 差错率极低 一般来讲只是在人工介入的地方才有可能发生错误 存储容量大 计算机的存储性是计算机区别于其他计算工具的重要特征 存储器不但能够存储大量的信息 而且能够快速准确地存入或取出
  • SQL分类及通用语法&&数据类型(超详细版)

    一 SQL分类 SQL是结构化查询语言 Structured Query Language 的缩写 它是一种用于管理和操作关系型数据库系统的标准化语言 SQL分类如下 DDL 数据定义语言 用来定义数据库对象 数据库 表 字段 DML 数据
  • 初入vue:子组件接收props值并需要对这个值进行修改的解决办法

    vue 子组件接收props值并需要对这个值进行修改的解决办法 最进刚刚从微信小程序转过来 发现了vue与其有很大的相似之处 相比之下vue确实是方便了很多 特别是vue的 双向绑定 对于组件的话vue方面限制了子组件对父组件穿来的值的修改
  • 用虚拟串口进行串口调试

    由于现在的笔记本电脑一般不带有串口 再进行串口调试时 可以用虚拟串口代替 虚拟串口下载链接 虚拟串口 Win7 下载 串口调试助手下载链接 串口调试助手 VS2010串口程序 使用的unicode库 纯API 不利用Mscomm控件 下载链
  • bulk interface驱动_USB驱动程序(较详细)一

    拓扑结构上 一个 USB 子系统并不是以总线的方式来分布 它是一棵由几个点对点连接构成的树 这些连接是连接设备和集线器的4线电缆 地 电源 和 2 个差分信号线 如同以太网的双绞线 USB主控制器负责询问每个USB设备是否有数据需要发送 由
  • ‘VB6EXT.OLB’ could not be registered

    打开VB6提示 VB6EXT OLB could not be registered 解决办法 用管理员打开 实测可行 参考 VB6 Error please help VBForums
  • el-select-dropdown 修改下拉框的样式

    问题描述 使用el select的时候有时候需要修改下拉框的样式 但是el select dropdown必须添加类名才能修改他的样式 问题解决 1 popper class element提供了为下拉框绑定类名的api 绑定类名之后使用
  • 利用python在网上接单赚钱,兼职也能月入过万,还不赶紧学起来

    看完这篇回答至少给你省去95 找答案的时间 我觉得python接单我是最有发言权的 从2016年进入大学 我就是一个不安分的学生 总是想着通过自己的技术来实现财富自由 我崇拜雷军 我觉得雷布斯不仅技术强 而且很有商业头脑 可是我是个呆呆的瓜
  • PID控制原理解释

    PID控制原理解释 文章目录 PID控制原理解释 0 前言 1 控制原理图解释 2 算法分析 3 PID数学模型解释 4 调参技巧说明 0 前言 参考网址 http blog gkong com liaochangchu 117560 as
  • Python 之os.walk()方法

    os walk方法 主要用来遍历一个目录内各个子目录和子文件 这个对于文件夹下遍历所有文件非常好用 对于数据处理也是很常见 os walk top topdown True nerr r None followlinks False 可以得
  • (转)关于Unity中的Input输入事件

    截获鼠标 键盘的消息 监听事件我们都是在Update里面监听的 Unity的虚拟轴打开 Edit gt Project Settings gt Input 打开的各个Name就是双引号里面要填的 记不住就打开查 也可以自己定义一些按键 一
  • visual studio:VC版本号与VS对应关系

    参考 VC版本号与VS对应关系
  • java解压zip压缩包

    坐在旁边的小伙伴问我怎么用 java 将服务器上的压缩文件解压出来 我索性给他写了个 demo 也顺手记录一下 亲测可用 如果觉得有帮助 欢迎点赞 评论 收藏 转发 java 实现解压 zip 压缩包 package com yuhuofe
  • Python获取文件夹中所有路径+名称

    获取文件夹中所有路径 名称 import os img dir r home aistudio data train out file home aistudio data train image paths txt with open o
  • package.json 同时执行多个命令

    在 package json 的 scripts 字段中 我们可以通过在命令中使用 连接符来同时执行多个命令 具体写法如下 Copy Code scripts command1 echo Command 1 ls al command2 c
  • 前端面试题(一) promise和async/await区别

    promise和async await都是处理异步请求 promise的用法 基本语法 promise共有三个状态 链式调用 错误捕获 async await 用法 错误捕获 区别 拓展 js中同步 异步 js的同步和异步问题通常是指aja
  • AR(增强现实) unity+vuforia 基础教程(2)!

    默认已经下载vuforia for unity 请移步到https developer vuforia com downloads sdk 1 打开unity 然后建立一个新的Project 2 点击Assets gt Import Pac
  • Java并发编程—线程池参数配置、线程池配置、线程池监控

    文章目录 一 线程池的参数配置 1 corePoolSize核心线程数选择 2 workQueue工作队列 阻塞队列 选择 3 阻塞队列长度和最大线程数选择 4 拒绝策略选择 二 SpringBoot环境下配置线程池 1 线程池配置 2 线