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并发编程—线程池参数配置、线程池配置、线程池监控 的相关文章

  • 透明平开窗

    我有一点JWindow上面有一个标志 用户可以将东西拖到上面 我主要在 OS X 上开发我的应用程序 为了获得我使用的透明窗口 setBackground new Color 0 0 0 0 在 Mac 上 这工作得很好 但在 Window
  • 设置 SWT Shell 的默认字体

    有没有办法为整个 Shell 设置默认字体 以便任何新控件都将使用相同的字体 看来现在我必须为我创建的每个控件设置字体 这导致了太多的冗余 默认使用的字体由平台选择 请参阅中的其他信息 类字体 SWT 标准小部件工具包 http book
  • 将 spring-security 与 spring-webflux 结合使用时禁用 WebSession 创建

    我正在使用 Rest api 运行无状态 spring boot 应用程序 并希望按照所述禁用 WebSessions 的创建https www baeldung com spring security session https www
  • 在 IntelliJ 上进行 Google App Engine Java 开发?

    令人烦恼的是 Google App Engine 已成为其中的另一个项目 他们只发布 Eclipse 插件 如 Spring Webflow 而我更喜欢 IntelliJ 你能用IntelliJ成功运行本地测试环境吗 并调试 部署本地或实时
  • 静态方法的 Java 内存模型

    我来自操作系统和 C 语言背景 在代码编译时 世界很简单 需要处理和理解堆栈 堆文本部分等 当我开始学习 Java 时 我确实了解 JVM 和垃圾收集器 我对静态方法感到很有趣 根据我的理解 类的所有实例都会在堆中创建 然后被清理 但是 对
  • 要打乱的键值(整数、字符串)列表的最佳结构

    我需要在 Java 中实现一个结构 它是一个键值列表 类型为整数 字符串 并且我想对其进行洗牌 基本上 我想做类似的事情 public LinkedHashMap
  • 在 Hibernate 中创建 UPDATE RETURNING 查询

    在 Oracle 中 我们可以创建一个更新查询 该查询将使用 RETURNING 子句返回更新的记录 Hibernate中有类似的功能吗 除了数据库生成的值之外 Hibernate 显然不需要返回更新的实例 因为对象传递给Session s
  • 正确使用 JDBC 连接池 (Glassfish)

    我需要在 Java Web 服务中作为会话 bean 实现数据库连接 但我不确定我这样做是否正确 我创建了一个类 public final class SQLUtils private static DataSource m ds null
  • 如何修复 Android 7.0 的 Spinner 模式下的 DatePickerDialog?

    我目前正在开发一个简单的项目 其中包含一个包含在 Web 视图中的网站 具有少量交互 以提高网站本身和 Android 移动设备之间的交互性 由于该网站包含用户生日的日期输入字段 因此我希望实现一个与所有设备兼容的旋转格式的日期选择器 我尝
  • 用 java 编写解释器时的 switch 或 if 语句

    当前的作业需要我编写一个程序 以一种非常微小且基本的编程语言 行为有点像 FORTRAN 来读取包含指令的文件并执行这些指令 基本上它是我猜的语言的简单解释器 它是完全线性的 所有语句都是按顺序定义的 并且只有字符串和整数变量 我需要查找和
  • Java 唤醒休眠线程

    我阅读了其他帖子 但没有找到我正在寻找的确切答案 所以我希望有人能给出一些澄清 我有一个将运行一段时间的程序 我有一些在后台运行的线程来执行各种任务 为了简单起见 让我们考虑 3 个线程 ThreadA每 10 秒执行一次任务 其中Thre
  • Java 泛型:如何为泛型类型指定类类型?

    我有一个 POJO 指定为 MyClass u where U是泛型类型参数 我正在尝试编写一个接受类引用的实用方法Class u
  • 在 eclipse 之外将 Spring MVC 应用程序部署到 tomcat 的幕后会发生什么?

    我猜想使用像 eclipse 这样很棒的 IDE 的一个缺点是你会忽略应用程序幕后发生的事情 我是一名 Ruby 开发人员 所以不是一名 Java 老手 所以我一直在用 java 编写一个项目 并使用 spring 框架进行 IOC 和 M
  • 如何从 Google Custom Search API 获取超过 100 个结果

    我正在尝试使用 Google Custom Search API 在 Java 中进行研究 因此 我需要为每个查询提供一个大的结果集 然而 我似乎仅限于前 100 个结果 这比我需要的要少得多 我使用这样的列表方法 list setStar
  • Java ConcurrentModificationException [重复]

    这个问题在这里已经有答案了 当删除倒数第二个元素时 没有 ConcurrentModificationException List
  • 如何使用云打印打印Android活动显示

    我正在尝试将 Google 云打印实现到应用程序中 遵循集成指南 https developers google com cloud print docs android 我试图通过打印 google com 来保持基本 单击我创建的打印按
  • 战争库中的罐子爆炸

    我们可以将分解的 jar 文件放入 war web inf 库中吗 它在 JBOSS 4 2 中对我不起作用 我收到以下错误并且无法部署应用程序 Caused by javax management RuntimeOperationsExc
  • 在服务器内部调用 Web 服务

    我有一个网络服务 getEmployee 当传递 id 时 它会获取单个员工的员工详细信息 同一服务器上的另一个 Web 服务 getEmployeeList 当传递一个部门时 它会获取整个员工列表 这将获取部门的 ID 然后调用 getE
  • scala中的协变类型参数需要在java接口中保持不变

    我有一个看起来像这样的特征 一些进一步的信息可以在我自己提出了这个相关问题 https stackoverflow com questions 3695990 inheritance and automatic type conversio
  • 如何使用剪辑来减少绘画时间?

    我正在尝试使用 Clip 来减少 CPU 负载 但剪辑在屏幕上留下了一些我似乎无法摆脱的垃圾 另外 打开和关闭剪辑似乎对 CPU 负载没有影响 在任一情况下 大部分时间似乎都花在重绘管理器和绘制缓冲图像上 import static jav

随机推荐

  • 拓端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 线