线程池一定需要了解的那些事

news2025/1/11 14:06:46

一、阿里Java开发规范,为啥禁止直接使用Executors创建线程池

  •  newFixdThreadPool 及 singleThreadPool 中默认队列长度为 Integer.MAX_VALUE,如果线程执行比较耗时,执行任务的线程在队列中产生大量堆积,进而有导致虚拟机OOM 的风险。
  public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
   }

 
   //默认长度 Integer.MAX_VALUE
   public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }
  • newCachedThreadPool 允许创建最大线程数量为 Integer.MAX_VALUE,当大量任务需要执行时,可能会导致大量线程的创建,每个线程默认占1M,线程占据资源过多或队列中线程产生堆积,导致 CPU 过高或 java虚拟机 OOM 的问题 。
   // 最大线程数 默认为:Integer.MAX_VALUE
   public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • 使用ThreadPoolExecutor 来构造线程池, 建议明确指定线程池的核心参数:最小线程数、最大线程数,队列长度、拒绝策略等等,确保线程池运稳定运行。

二、如何合理配置线程池的大小

  •  CPU 密集型: 主要执行计算任务,响应时间较快,任务 cpu 的利用率很高。线程数的配置由服务器 CPU 核心数来决定, 建议CPU 核心数=同时最大执行线程数,如 CPU 核心数为 8,表明服务器最多能同时执行 8个线程。创建过多的线程反而会导致线程之间上下文切换,降低执行效率。推荐:线程池的最大线程数= cpu 核心数+1。
  •  IO 密集型: 主要进行 IO 操作,执行 IO 操作(文件读写、网络通信等)相对比较耗时,cpu相对处于空闲状态, 导致 cpu 的利用率不高,建议可以增加线程的数量。IO密集型操作建议结合线程的等待时长来做判断,等待时间越长,线程数相对配置的越多。一般建议配置 cpu 核心数的 2 倍。 基础公式:线程池设定最佳线程数目 = ((线程池配置的线程等待时间+线程 CPU 时间)/ 线程 CPU 时间 )* CPU 数目 。公式中线程 cpu等待时间是计算出程序中单个线程在 cpu 上运行的时间。

三、线程池中的线程的初始化

         线程池创建后,线程池默认没有初始化,简而言之就是线程池中没有线程,在提交任务之后才会创建线程。 在并发系统中,为提高系统的吞吐量,建议在线程池创建之后立即创建线程。通过以下两个方法可以实现线程的初始化:

        ExecutorService executorService = new ThreadPoolExecutor(10,20,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>());
        ThreadPoolExecutor threadPoolExecutor=(ThreadPoolExecutor)executorService;
        //方式1 初始化所有核心线程
        threadPoolExecutor.prestartAllCoreThreads();
        //方式2 初始化一个核心线程
        threadPoolExecutor.prestartCoreThread();

四、线程池的关闭

  • shutdown():不会立即终止线程池,等所有任务队列中的任务都执行完后才终止,同时也不会接受新的任务 。
  • shutdownNow():立即终止线程池,并尝试打断正在执行的任务且清空任务队列,返回未执行的任务。

五、线程池核心参数支持动态调整及线程池监控

  • setCorePoolSize:设置核心线程数
    public void setCorePoolSize(int corePoolSize) {
        if (corePoolSize < 0)
            throw new IllegalArgumentException();
        int delta = corePoolSize - this.corePoolSize;
        this.corePoolSize = corePoolSize;
        if (workerCountOf(ctl.get()) > corePoolSize)
            interruptIdleWorkers();
        else if (delta > 0) {
            // We don't really know how many new threads are "needed".
            // As a heuristic, prestart enough new workers (up to new
            // core size) to handle the current number of tasks in
            // queue, but stop if queue becomes empty while doing so.
            int k = Math.min(delta, workQueue.size());
            while (k-- > 0 && addWorker(null, true)) {
                if (workQueue.isEmpty())
                    break;
            }
        }
    }
  • setMaximumPoolSize:设置线程池最大线程数目
   public void setMaximumPoolSize(int maximumPoolSize) {
        if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
            throw new IllegalArgumentException();
        this.maximumPoolSize = maximumPoolSize;
        if (workerCountOf(ctl.get()) > maximumPoolSize)
            interruptIdleWorkers();
    }
  • beforeExecute:  获取执行之前的核心参数
  • afterExecute:  获取执行之后的核心参数

    protected void beforeExecute(Thread t, Runnable r) {
        BlockingQueue<Runnable> blockingQueue = getQueue();

        log.info("执行前! 线程池名称:{},初始线程数:{},核心线程数:{},活跃的任务数量:{},已经执行的任务数:{},任务总数:{},允许最大的线程数:{}," +
                        "线程允许空闲时间:{},队列的容量:{}",name,getPoolSize(),getCorePoolSize(),getActiveCount(),getCompletedTaskCount(),
                getTaskCount(),getMaximumPoolSize(),getKeepAliveTime(TimeUnit.MILLISECONDS),(blockingQueue.size() + blockingQueue.remainingCapacity()));
    }

    /**
     * @description: 线程监控使用
     * @param: r
     * @param: t
     * @return: void
     * @author: 
     * @date: 2022/1/17 16:58
     */
    protected void afterExecute(Runnable r, Throwable t) {
        BlockingQueue<Runnable> blockingQueue = getQueue();
        log.info("执行后! 线程池名称:{},初始线程数:{},核心线程数:{},活跃的任务数量:{},已经执行的任务数:{},任务总数:{},允许最大的线程数:{}," +
                        "线程允许空闲时间:{},队列的容量:{}",name,getPoolSize(),getCorePoolSize(),getActiveCount(),getCompletedTaskCount(),
                getTaskCount(),getMaximumPoolSize(),getKeepAliveTime(TimeUnit.MILLISECONDS),(blockingQueue.size() + blockingQueue.remainingCapacity()));

    }

六、推荐开源线程池监控 Hippo4j

  • 动态可观测线程池框架,为业务系统提高线上运行保障能力

 

 

 官网:Hippo4j | Hippo4j

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

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

相关文章

罗德与施瓦茨网络分析仪RSZVA40

ZVA40 主要特点 台具有以下特点的矢量网络分析仪 带 4 个内部信号源&#xff0c;频率高达 67 GHz&#xff0c;可以快速地对放大器和混频器进行测量 具有 4 个相位相干信号发生器功能&#xff08;频率可高达 67 GHz&#xff09; 壹捌叁贰零玖壹捌陆伍叁 中频带宽可高达 30 …

2023国赛数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 最短时…

一、pikachu之SQL注入(1)

文章目录 一、SQL注入步骤二、数字型注入(post注入)三、字符型注入(get)四、搜索型注入五、XX型注入六、“insert/updata”注入 一、SQL注入步骤 寻找传参页面&#xff1b;判断是否存在注入点&#xff1b; 字符型注入&#xff1f;数字型注入&#xff1f; 判断字段的数量&#…

引领娱乐潮流:邀请明星办个人演唱会的五大关键步骤

随着娱乐产业的不断壮大和观众对明星的热情高涨&#xff0c;举办个人演唱会已经成为了一种广受欢迎的文化现象。这种活动不仅让粉丝们有机会亲身近距离感受偶像的音乐魅力&#xff0c;同时也为明星和品牌提供了一个宝贵的互动平台。然而&#xff0c;要成功地邀请明星办个人演唱…

Prometheus监控之SNMP Exporter介绍和数据展现

1 SNMP协议介绍 SNMP协议全称是&#xff1a;Simple Network Management Protocol&#xff0c;译为简单网络管理协议&#xff0c;是作为TCP/IP网络管理标准协议&#xff0c;为不同的设备提供统一接口&#xff0c;实现了网络设备之间的统一管理。 SNMP协议分为三个版本&#xf…

Java-进程调度算法

文章目录 为什么要设置进程调度算法&#xff1f;分类1. 先进先出&#xff08;FIFO&#xff09;算法优缺点FIFO代码示例 2. 短作业优先&#xff08;SJF&#xff09;算法优缺点示例代码 3. 优先级算法&#xff08;Priority scheduling&#xff09;优缺点示例代码 4. 时间片轮转算…

java 高级面试题整理(薄弱技术)

session 和cookie的区别和联系 session1.什么是session Session是另一种记录客户状态的机制&#xff0c;不同的是Cookie保存在客户端浏览器中&#xff0c;而Session保存在服务器上。客户端浏览器访问服务器的时候&#xff0c;服务器把客户端信息以某种形式记录在服务器上。这就…

Wireshark数据抓包分析之HTTP协议

一、实验目的&#xff1a; 主要时熟悉wireshark的使用 二、预备知识&#xff1a; HTTP协议的相关知识 what fk&#xff0c;原来只要在右页点击切换&#xff0c;就可以开启2台不同的机器欸&#xff01;nice 三、实验过程&#xff1a; 1.在机器1中通过管理员身份运行hfs之后&a…

5G网络优化基础班9月11号开班已定,零基础系统教学,带你入门+进阶+实战+就业!

1G、2G、3G时代&#xff0c;更多的是让人们了解和开始使用移动通讯&#xff0c;而随着技术的不断地迭代更新&#xff0c;4G改变生活&#xff0c;5G或将改变社会。5G是第五代移动通信技术的简称&#xff0c;它是一种全新的无线通信技术&#xff0c;将为人们带来更快、更稳定、更…

1.文章复现《热电联产系统在区域综合能源系统中的定容选址研究》(附matlab程序)

0.代码链接 文章复现《热电联产系统在区域综合能源系统中的定容选址研究》&#xff08;matlab程序&#xff09;-Matlab文档类资源-CSDN文库 1.简述 本文采用遗传算法的方式进行了下述文章的复现并采用电-热节点的方式进行了潮流计算以降低电网的网络损耗 分析了电网的基本数…

Java学习笔记38

Java笔记38 注解 什么是注解 Annotation是从 JDK 5.0 开始引入的新技术。Annotation的作用︰ 不是程序本身&#xff0c;可以对程序作出解释。&#xff08;这一点和注释 - comment没什么区别&#xff09;可以被其他程序&#xff08;比如编译器等&#xff09;读取。 Annotatio…

系统认知篇:防腐层、门面模式及适配模式的本质

门面模式和适配器模式是代码级的设计模式&#xff0c;而防腐层本质是一种 防御型策略 &#xff0c;在更高的层级对系统进行解耦 1 关于防腐层 Anti-Corruption Layer(ACL) 如下&#xff1a; Implement a faade or adapter layer between different subsystems that dont share…

用断言更好地实现替换重复出现的单词

断言是指对匹配到的文本位置有要求。也就是说&#xff0c;在有些情况下&#xff0c;我们对要匹配的文本的位置也有一定的要求。为了解决这个问题&#xff0c;正则中提供了一些结构&#xff0c;只用于匹配位置&#xff0c;而不是文本内容本身&#xff0c;这种结构就是断言。常见…

C++_Linux报错问题记录

1、致命错误&#xff1a;vector&#xff1a;没有那个文件或目录 解决&#xff1a;.c文件只会引用C语言的标准库&#xff0c;vecter是属于C的语法&#xff0c;把文件名称改成cpp即可 2、.cpp文件中下面编译语句报错&#xff1a;对‘std::cout’未定义的引用 gcc -o test test.…

docker 报错

问题说明&#xff1a;我是服务器上面的docker拉到本地30卡想用的&#xff0c;但是失败&#xff0c;报错如下&#xff1a; 服务器上面显存驱动是450&#xff0c;本地30卡驱动是470 nvidia-docker run -it --name 20230821_3 --shm-size 16g -p 10029:22 --privileged 20230821_i…

关于cloudflare的“检查站点连接是否安全”一直反复转圈的问题

前一段时间访问不少网站都会出现类似以下的信息&#xff1a; 其中很多时候哦是没有红色框框一栏&#xff0c;就是拼命在转圈和刷新页面&#xff0c;等上一个小时都没用。以上情况看很多网上的说法是卸载浏览器安装的插件。我寻思我也没安装过什么插件。 对于试过网上不少方法但…

java八股文面试[java基础]—— hashCode 与 equals 区别 == 与 equals的区别

两个对象的hashCode()相同时&#xff0c;equals()相等吗&#xff1f;_两个对象的hashcode一样,equal一样么_不想当个程序员的博客-CSDN博客 equals()&#xff1a;比较的是非基本类型的数据的引用地址&#xff08;即内存地址&#xff09;是否相同&#xff0c;但是对于重写equal…

Vulnhub: DOUBLE: 1靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.209 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.209 目标80端口 sendcommand.php页面源码 写入webshell <?php system($_GET["cmd"]);?> 执行命令 ht…

不修改原图片,自动添加水印

只要添加我写的一个DynaWatermark2.1.1.jar的包,然后在web.xml里配置一下,哪个文件夹下的图片需要动态水印,就可以啦!以后通过页面访问这个文件夹下的图片,就会自动加上水印.但不会修改文件夹里图片本身.   这个jar里面有添加图片水印和文字水印两个servlet.(不能两个都配置,…

《golang设计模式》第二部分·结构型模式-03-组合模式(Composite)

文章目录 1. 概述1.1 角色1.2 类图 2. 代码示例2.1 设计2.2 代码2.3 类图 1. 概述 将叶子节点和复合节点组合起来&#xff0c;定义一个抽象接口遍历他们 1.1 角色 Component&#xff08;抽象构件&#xff09;&#xff1a;为叶子构件和复合构件声明接口&#xff0c;定义了结构…