线程池详解
线程池
什么是线程池:线程池就是管理一系列线程的资源池。
当有任务要处理时,直接从线程池中获取线程来处理,处理完之后线程并不会立即被销毁,而是等待下一个任务。
为什么要用线程池 / 线程池的好处:
-
**降低资源消耗。**通过重复利用已创建的线程降低线程创建和销毁造成的消耗
-
**提高响应速度。**当任务到达时,任务可以不需要等到线程创建久能立即执行。
-
**提高线程的可管理性。**统一管理线程,避免系统创建大量同类线程而导致消耗完内存。
线程池的应用:
比如我们系统 Web 服务器用的 Tomcat,Tomcat 处理每一个请求都会从线程连接池里面用一个线程去处理,又比如说我们连接数据库会用对应连接池 Druid德鲁伊等
还有实际开发中的定时任务,该任务的链路执行时间和过程都非常长,就会用一个线程池将该定时任务的请求进行处理。这样做好处就是可以及时返回结果给调用方,能够提高系统的吞吐量
// 请求直接交给线程池来处理
public void push(PushParam pushParam) {try {pushServiceThreadExecutor.submit(() -> {handler(pushParam);});} catch (Exception e) {logger.error("pushServiceThreadExecutor error, exception{}:", e);}
}
如何创建线程池
- 通过 ThreadPoolExecutor 构造函数来创建(推荐)
- 通过 Executor 框架的工具类 Executors 来创建
为什么不推荐使用内置线程池(通过 Executor 框架的工具类 Executors 来创建):通过 ThreadPoolExecutor 构造函数的方式,这样的处理方式让开发人员更加明确线程池的运行规则,规避资源耗尽的风险
线程池常见参数有哪些
ThreadPoolExecutor 3个最重要的参数:
-
corePoolSize:任何队列未达到队列容量时,最大可以同时运行的线程数量
-
maxinumPoolSize:当任务队列存放的任务达到队列容量的时候的最大线程数量。任何队列中存放的任务达到队列容量的时候,会创建新的线程运行任务。否则根据拒绝策略处理新任务。
-
workQueue:任务队列:新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中
keepAliveTime:线程池中的线程数量大于
corePoolSize的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了keepAliveTime才会被回收销毁。非核心线程空闲后,保持存活的时间;设置为0,表示多余的空闲线程会被立即终止unit:
keepAliveTime参数的时间单位threadFactory:
handler:饱和策略
线程池的饱和策略:
- ThreadPoolExecutor.AbortPolity:抛出 RejectedExecutionException来拒绝新任务的处理
- ThreadPoolExecutor.CallerRunsPolicy:
- ThreadPoolExecutor.DiscardPolicy:
- .DiscardPolicy:
- .DiscardOldestPolicy:
如何处理这些参数 / 线程池大小怎么设置
CPU密集型任务(N + 1)
消耗CPU资源,将线程数设置为 N(CPU 核心数)+1,比 CPU 核心数多出来一个线程是为了防止线程阻塞、锁等原因导致的任务暂停带来的影响。一旦某个线程被阻塞,释放了 cpu 资源,多一个线程就可以充分利用 CPU 的空闲时间
IO密集型
系统会用大部分时间处理 I/O 操作,而线程等待 I/O 操作会被阻塞,释放CPU资源,这是就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务应用中,可以多配置一些线程:
最佳线程数 = CPU核心数 * (1/CPU利用率) = CPU 核心数 * (1 + (I/O耗时 / CPU耗时))
线程池过小:当有大量请求需要处理,系统响应比较慢影响体验,甚至会出现在任务队列大量堆积导致OOM
线程池过大:大量线程同时争取 CPU 资源,这样会导致大量的上下文切换,增加线程执行时间,影响整体执行效率
CPU密集型、IO密集型
如果你的应用主要是利用cpu计算,也就是更多的是消耗cpu资源的话,那么就是cpu密集型,如果更多的是和IO相关的,比如接收一个前端请求--解析参数--查询数据库--返回给前端这样的,那么就是IO密集型的。
线程池处理任务的流程

- 如果当前运行的线程数小于核心线程数,那么就会新建一个线程来执行任务
- 如果当前运行的线程数等于或大于核心线程数,但是小于最大线程,那么就把该任务放入到任务队列里等待执行
- 如果向任务队列投放任务失败,但是当前运行的线程数是小于最大线程数的,就新建一个线程来执行任务
- 如果当前运行的线程数已经等同于最大线程数了,新建线程将会是当前运行的线程超出最大线程数,那么当前任务会被拒绝,饱和(拒绝)策略会调用RejectedExecutionHandler.rejectedExecution() 方法
Excetors 工具类提供了哪些线程池?有什么问题吗?
Excetors 工具类提供的常见线程池如下:
FixedThreadPool:固定线程数量的线程池。该线程池中的线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。SingleThreadExecutor:只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务。CachedThreadPool:可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。ScheduledThreadPool:给定的延迟后运行任务或者定期执行任务的线程池。
Excetors 工具类提供的常见线程池的弊端如下:
FixedThreadPool和SingleThreadExecutor:使用的是无界的LinkedBlockingQueue,任务队列最大长度为Integer.MAX_VALUE,可能堆积大量的请求,从而导致 OOM。CachedThreadPool:使用的是同步队列SynchronousQueue, 允许创建的线程数量为Integer.MAX_VALUE,如果任务数量过多且执行速度较慢,可能会创建大量的线程,从而导致 OOM。ScheduledThreadPool和SingleThreadScheduledExecutor:使用的无界的延迟阻塞队列DelayedWorkQueue,任务队列最大长度为Integer.MAX_VALUE,可能堆积大量的请求,从而导致 OOM。
相关文章:
线程池详解
线程池 什么是线程池:线程池就是管理一系列线程的资源池。 当有任务要处理时,直接从线程池中获取线程来处理,处理完之后线程并不会立即被销毁,而是等待下一个任务。 为什么要用线程池 / 线程池的好处: **降低资源消…...
mybatis(5)参数处理+语句查询
参数处理+语句查询 1、简单单个参数2、Map参数3、实体类参数4、多参数5、Param注解6、语句查询6.1 返回一个实体类对象6.2 返回多个实体类对象 List<>6.3 返回一个Map对象6.4 返回多个Map对象 List<Map>6.5 返回一个大Map6.6 结果映射6.6.1 使用resultM…...
数据应用OneID:ID-Mapping Spark GraphX实现
前言 说明 以用户实体为例,ID 类型包含 user_id 和 device_id。当然还有其他类型id。不同id可以获取到的阶段、生命周期均不相同。 device_id 生命周期通常指的是一个设备从首次被识别到不再活跃的整个时间段。 user_id是用户登录之后系统分配的唯一标识ÿ…...
第6章 6.2.3 : readlines和writelines函数 (MATLAB入门课程)
讲解视频:可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。 MATLAB教程新手入门篇(数学建模清风主讲,适合零基础同学观看)_哔哩哔哩_bilibili 在MATLAB的文本数据处理任务中,导入和导出文件是常…...
Matlab应用层生成简述
基础软件层 目前接触到的几款控制器,其厂商并没有提供simulink的基础软件库一般为底层文件被封装为lib,留有供调用API接口虽然能根据API接口开发基础软件库,但耗费时间过长得不偿失 应用层 所以可以将应用层封装为一个子系统,其…...
每日一题(leetcode1702):修改后的最大二进制字符串--思维
找到第一个0之后,对于后面的子串(包括那个0),所有的0都能调上来,然后一一转化为10,因此从找到的第一个0的位置开始,接下来是(后半部分子串0的个数-1)个1,然后…...
PHP自助建站系统,小白也能自己搭建网站
无需懂代码,用 自助建站 做企业官网就像做PPT一样简单,您可以亲自操刀做想要的效果! 自助建站是一款简单、快捷、高效的工具,可以帮助您制作响应式网站。我们的自助建站系统,将传统的编码工作转化为直观的拖拽操作和文…...
计算机视觉 | 基于 ORB 特征检测器和描述符的全景图像拼接算法
Hi,大家好,我是半亩花海。本项目实现了基于 ORB 特征检测器和描述符的全景图像拼接算法,能够将两张部分重叠的图像拼接成一张无缝连接的全景图像。 文章目录 一、随机抽样一致算法二、功能实现三、代码解析四、效果展示五、完整代码 一、随机…...
Scala - 函数柯里化(Currying)
柯里化(Currying)指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。 实例 首先我们定义一个函数: def add(x:Int,y:Int)xy 那么我们应用的时候,应该是这样用:add(1,2) 现在我们把这…...
Switch-case
Java switch case 语句 switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。 语法 switch case 语句语法格式如下: switch(expression){case value ://语句break; //可选case value ://语句break; //可选//你可以有任意数量…...
蓝桥杯-单片机基础16——利用定时计数中断进行动态数码管的多窗口显示
综合查阅了网络上目前能找到的所有关于此技能的代码,最终找到了下述方式比较可靠,且可以自定义任意显示的数值。 传统采用延时函数的方式实现动态数码管扫描,在题目变复杂时效果总是会不佳,因此在省赛中有必要尝试采用定时计数器中…...
2024/4/5—力扣—下一个排列
代码实现: 思路:两遍扫描 void swap(int *a, int *b) {int t *a;*a *b;*b t; }void reverse(int *nums, int l, int r) {while (l < r) {swap(nums l, nums r);l;r--;} }void nextPermutation(int *nums, int numsSize) {int i numsSize - 2;wh…...
xss.pwnfunction-Ugandan Knuckles
这个是把<>过滤掉了所以只能用js的事件 ?weya"onfocus"alert(1337)" autofocus"...
LabVIEW和2D激光扫描的受电弓滑板磨耗精确测量
LabVIEW和2D激光扫描的受电弓滑板磨耗精确测量 在电气化铁路运输中,受电弓滑板的健康状况对于保障列车安全行驶至关重要。受电弓滑板作为连接电网与列车的直接介质,其磨损情况直接影响到电能的有效传输及列车的稳定运行。精确、快速测量受电弓滑板磨损情…...
Linux第87步_阻塞IO实验
阻塞IO是“应用程序”对“驱动设备”进行操作,若不能获取到设备资源,则阻塞IO应用程序的线程会被“挂起”,直到获取到设备资源为止。 “挂起”就是让线程进入休眠,将CPU的资源让出来。线程进入休眠后,当设备文件可以操…...
C/C++基础----常量和基本数据类型
HelloWorld #include <iostream>using namespace std;int main() {// 打印cout << "Hello,World!" << endl;return 0; }c/c文件和关系 c和c是包含关系,c相当于是c的plus版本c的编译器也可以编译c语言c文件.cpp结尾.h为头文件.c为c语言…...
什么是生成式AI?有哪些特征类型
生成式AI是人类一种人工智能技术,可以生成各种类型的内容,包括文本、图像、音频和合成数据。那么什么是人工智能?人工智能和机器学习之间的区别是什么?有哪些技术特征? 人工智能是一门学科,是计算机科学的一…...
《Linux C/C++服务器开发实践》之第7章 服务器模型设计
《Linux C/C服务器开发实践》之第7章 服务器模型设计 7.1 I/O模型7.1.1 基本概念7.1.2 同步和异步7.1.3 阻塞和非阻塞7.1.4 同步与异步和阻塞与非阻塞的关系7.1.5 采用socket I/O模型的原因7.1.6(同步)阻塞I/O模型7.1.7(同步)非阻…...
SSH穿透ECS访问内网RDS数据库
处于安全考虑,RDS一般只会允许指定的IP进行访问,而我们开发环境的IP往往是动态的,每次IP变动都需要去修改RDS的白名单,为我们的工作带来很大的不便。 那么如何去解决这个问题? 假如我们有一台ESC服务器,E…...
python 有哪些函数
Python内置的函数及其用法。为了方便记忆,已经有很多开发者将这些内置函数进行了如下分类: 数学运算(7个) 类型转换(24个) 序列操作(8个) 对象操作(7个) 反射操作(8个) 变量操作(2个) 交互操作(2个) 文件操作(1个) 编译执行(4个) 装饰器(3个) …...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...
