线程池再思考(业务学习)

1.为什么要用线程池?

**1.降低资源消耗,**复用已创建的线程来降低创建和销毁线程的消耗。
2.提高响应速度,任务到达时,可以不需要等待线程的创建立即执行。
3.提高线程的可管理性,使用线程池能够统一的分配、调优和监控。

2.线程池的概述:

Java中线程池的核心实现类是ThreadPoolExecutor,可以通过该类地构造方法来构造一个线程池,我们先来看下ThreadPoolExecutor的整个继承体系
我们可以通过ThreadPoolExecutor去构造一个线程池
**Executor接口:**提供了将任务的执行和线程的创建以及使用解耦开来的抽象
ExecutorService接口继承了Executor接口,在Executor的基础上,增加了一些关于管理线程池本身的一些方法,比如查看任务的状态、stop/terminal线程池、获取线程池的状态等等。
请添加图片描述

3.ThreadPoolExcutor的组成

1.corePoolSize:,核心线程数量,决定是否创建新的线程来处理到来的任务
2.maximumPoolSize:,最大线程数量,线程池中允许创建线程地最大数量
3.keepAliveTime:,线程空闲时存活的时间
4.unit:,空闲存活时间单位
5.workQueue:,任务队列,用于存放已提交的任务
6.threadFactory:,线程工厂,用于创建线程执行任务
7.handler:拒绝策略,当线程池处于饱和时,使用某种策略来拒绝任务提交

重点讲下几个拒绝策略:
1😗*AbortPolicy,**抛出异常,让用户可根据具体任务来做出具体的判断
2😗*DiscardPolicy,**什么也不做,直接丢弃任务
3😗*DiscardOldestPolicy,**将阻塞队列中的任务poll出来,然后执行当前任务
4:CallerRunsPolicy,提交任务的线程来执行任务

3.1执行流程:

1)如果workerCount < corePoolSize ==> 创建线程执行提交的任务
2)如果workerCount >= corePoolSize && 阻塞队列未满 ==> 添加至阻塞队列,等待后续线程来执行提交地任务
3)如果workerCount >= corePoolSize && workerCount < maxinumPoolSize && 阻塞队列已满 ==> 创建非核心线程执行提交的任务
4)如果workerCount >= maxinumPoolSize && 阻塞队列已满 ==> 执行拒绝策略

请添加图片描述

4.线程池的几种状态:

请添加图片描述

5.自定义线程工厂,给线程池与线程统一管理

根据不同的线程池,设置名称,方便管理线程,以及设置他们的名称,当出现异常时,方便定位排查问题

package com.wyh.subject.domain.config;import org.apache.commons.lang3.StringUtils;import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;/*** 自定义线程工厂:1.用于生成具有自定义名称、优先级的线程。* 1.它实现了ThreadFactory接口,并提供了一个构造函数来设置线程名称的前缀。* 2.通过调用newThread方法,可以创建一个新的线程,并设置线程的相关属性,例如线程组、名称、优先级等。这个自定义线程工厂可以在使用线程池时,为线程提供更加可读性和可管理性的名称。*/
public class CustomNameThreadFactory implements ThreadFactory {// 定义一个线程池数量的静态变量,用于生成线程池的序号private static final AtomicInteger poolNumber = new AtomicInteger(1);/*** 线程组的主要作用有:** 1.统一管理和控制:将多个线程归为一个组,可以方便地对这些线程进行批量操作,例如挂起、恢复、中断等。* 2.设置优先级:线程组可以设置一个默认的优先级,所有在该组中创建的线程都将继承这个优先级。* 3.监控状态:通过线程组,可以方便地监控该组中的所有线程的状态和运行情况,从而更加精细地调整程序的运行效率。*/private final ThreadGroup group;// 定义一个线程数量的静态变量,用于生成线程的序号private final AtomicInteger threadNumber = new AtomicInteger(1);// 定义一个线程名称的前缀private final String namePrefix;// 构造函数,接受一个线程名称作为参数public CustomNameThreadFactory(String name) {// 获取当前线程的安全管理器SecurityManager s = System.getSecurityManager();// 如果存在安全管理器,则将当前线程的线程组设置为安全管理器的线程组group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();// 如果没有提供线程名称,则使用默认名称 "pool"if (StringUtils.isBlank(name)) {name = "pool";}// 将线程名称的前缀设置为提供的名称和当前线程池的序号namePrefix = name + "-" + poolNumber.getAndIncrement() + "-thread-";}// 重写 newThread() 方法,用于生成具有自定义名称的线程@Overridepublic Thread newThread(Runnable r) {// 创建一个新线程Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);// 如果新线程是守护线程,则将其设置为非守护线程if (t.isDaemon()) {t.setDaemon(false);}// 如果新线程的优先级不为常规优先级,则将其设置为常规优先级if (t.getPriority() != Thread.NORM_PRIORITY) {t.setPriority(Thread.NORM_PRIORITY);}// 返回新线程return t;}}

6.如何确定线程池的线程数

1.公式:
CPU核心线程数目标CPU利用率(1+w/c)
在这里插入图片描述
2.例子:
如果我期望目标利用率为90%(多核90),那么需要的线程数为:
核心数12 * 利用率0.9 * (1 + 50(sleep时间)/50(循环50_000_000耗时)) ≈ 22
现在把线程数调到22,看看结果:
在这里插入图片描述
3.但是,所以受环境干扰下,单靠公式很难准确的规划线程数,一定要通过测试来验证。

  1. 析当前主机上,有没有其他进程干扰(比如其他框架或者中里面封的线程池)
  2. 分析当前JVM进程上,有没有其他运行中或可能运行的线程
  3. 设定目标
  4. 目标CPU利用率 - 我最高能容忍我的CPU飙到多少?
  5. 目标GC频率/暂停时间 - 多线程执行后,GC频率增高,最大能容忍到什么频率,每次暂停时间多少?
    因为线程数增加系统资源竞争就会增加,CPU的竞争就会增加,那么就会影响GC的效率无法获取充分的资源
  6. 执行效率 - 比如批处理时,我单位时间内要开多少线程才能及时处理完毕
  7. ……
  8. 梳理链路关键点,是否有卡脖子的点,因为如果线程数过多,链路上某些节点资源有限可能会导致大量的线程在等待资源(比如三方接口限流,连接池数量有限,RPC调用中间件压力过大无法支撑等)
  9. 不断的增加/减少线程数来测试,按最高的要求去测试,最终获得一个“满足要求”的线程数**

所以,我们需要分析以上情况才能真正确定所需线程数

4.策略:
1.逐步增加/减少:首先可以通过逐步增加或减少线程数的方式来测试系统的性能和指标变化。具体来说,可以从一个较小的线程数量开始,逐渐增加线程数,直到达到目标要求或者性能受到影响;或者从一个较大的线程数量开始,逐渐减少线程数,直到达到目标要求或者性能受到影响。这种方法可以帮助找到最优的线程数。
2.监控工具:使用多种监控工具,包括JVM自带的jstat、jconsole、jvisualvm,以及第三方工具如VisualVM、YourKit等,收集系统性能数据,分析线程数对系统性能的影响。去直观地查看线程数CPU 使用率内存占用等指标,帮助实时
监控系统性能
,并调整线程数以优化性能

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

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

相关文章

字符设备驱动分步注册过程实现LED驱动的编写,编写应用程序测试

头文件&#xff01;&#xff01;&#xff01;&#xff01; #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }gpio_t; #define PHY_LED1_ADDR 0…

二叉树(4)——链式二叉树

1 二叉树的概念 二叉树是&#xff1a; 空树非空&#xff1a;根节点&#xff0c;根节点的左子树、根节点的右子树组成的。 二叉树定义是递归式的&#xff0c;因此后序基本操作中基本都是按照该概念实现的。 2 二叉树的遍历 2.1 前序、中序以及后序遍历 学习二叉树结构&#xf…

N叉树的前序遍历

1.题目 这道题是2024-2-18的签到题&#xff0c;题目难度为简单。 考察的知识点为DFS算法&#xff08;树的前序遍历&#xff09;。 题目链接&#xff1a;N叉树的前序遍历 给定一个 n 叉树的根节点 root &#xff0c;返回 其节点值的 前序遍历 。 n 叉树 在输入中按层序遍历…

天锐绿盾 | 办公终端文件数据\资料防泄密软件

天锐绿盾是一款电脑文件防泄密软件&#xff0c;旨在帮助企业保护其敏感数据免受未经授权的访问和泄露。该软件采用先进的加密技术和文件监控机制&#xff0c;确保企业数据在存储、传输和使用过程中的安全性。 PC地址&#xff1a;https://isite.baidu.com/site/wjz012xr/2eae091…

华清作业day57

效果图&#xff1a; 头文件&#xff1a; #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }gpio_t; #define PHY_LED1_ADDR 0X50006000 #define…

MySQL之json数据操作

1 MySQL之JSON数据 总所周知&#xff0c;mysql5.7以上提供了一种新的字段格式json&#xff0c;大概是mysql想把非关系型和关系型数据库一口通吃&#xff0c;所以推出了这种非常好用的格式&#xff0c;这样&#xff0c;我们的很多基于mongoDB的业务都可以用mysql去实现了。当然…

【JavaScript】输入输出语法

目录 一、输出语法 二、输入语法 一、输出语法 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>D…

【c++】STL之stack和queue详解

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;掌握stack和queue库&#xff0c;了解deque库 >…

Junit测试套件(Test Suite)

0. 什么是测试套件 对多个测试类的统一执行 只有一个测试类 点击一下执行就好有 5个测试类 分别打开 挨个点执行有100个测试类 &#xff1f;&#xff1f;分别点开执行 为100个测试类创建一个测试套件&#xff0c;然后再执行一次测试套件 √ 一个测试套件“囊括“三个测试类…

数据在内存中的存储以及百度笔试题

目录 一.整型家族 什么是大小端存储&#xff08;百度笔试题&#xff09; 大端字节序存储 小端字节序存储 为什么要讨论大小端字节序存储 写一个程序判断是大端还是小端存储&#xff08;百度笔试题&#xff09; 思路&#xff1a;用1去判断&#xff0c;如果返回1则是小端&a…

SHERlocked93 的 2023 年终总结

工作之后感觉一年一年过的太快&#xff0c;没有个记录连回忆都无从回忆起&#xff0c;之前的年终总结&#xff1a; SHERlocked93 的 2022 年终总结SHERlocked93 的 2021 年终总结SHERlocked93 的 2020 年终总结SHERlocked93 的 2019 年终总结SHERlocked93 的 2018 年终总结SHER…

静态时序分析:SDC约束命令set_clock_latency详解

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 时钟的延迟可以使用set_clock_latency命令设置&#xff0c;这里的时钟延迟包括源延迟(source latency)&#xff0c;即时钟对象到时钟源对象&#xff08;时钟定义…