ThreadPool-线程池使用及原理
1. 线程池使用方式
示例代码:
// 一池N线程
Executors.newFixedThreadPool(int)
// 一个任务一个任务执行,一池一线程
Executors.newSingleThreadExecutorO
// 线程池根据需求创建线程,可扩容,遇强则强
Executors.newCachedThreadPool()
// 自定义线程池方式
new ThreadPoolExecutor(...)
注:一般在工作中都是根据业务场景进行自定义线程池,进行使用;
自定义线程池方法;详见后面章节:自定义线程池
2. 线程池底层工作原理
a. 线程池参数:
线程池,具有多个参数:具有各自的含义:
七参数:
- corePoolSize:核心线程数,一直保持活跃状态的线程
- maximumPoolSize:最大线程数,线程池能容纳的最大线程数量
- keepAliveTime:空闲线程存活时间,非核心线程的空闲存活时间
- unit:存活的时间单位,非核心线程的空闲存活时间单位
- workQueue:存放未执行任务的队列
- threadFactory:线程工厂,创建线程的工厂类
- handler:拒绝策略,队列满了和达到最大线程数后的拒绝策略
如图:
b. 线程池的拒绝策略
AbortPolicy:默认,直接抛出RejectedExcutionException异常,阻止系统正常运行
CallerRunsPolicy:该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者
DiscardPolicy:直接丢弃任务,不予任何处理也不抛出异常,如果允许任务丢失,这是一种好方案
DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务
c. 线程池底层工作原理
-
在创建了线程池后,如果设置了核心线程数(corePoolSize),则线程池中的线程数会先创建相应数量的核心线程。如果没有任务到达,这些核心线程会保持活动状态。
-
当调用execute()方法添加一个请求任务时,线程池会根据以下判断来决定任务的执行方式:
- 如果正在运行的线程数量小于核心线程数(corePoolSize),则会立即使用核心线程来执行任务。
- 如果正在运行的线程数量大于或等于核心线程数,但任务队列未满,则任务会被放入队列中等待执行。
- 如果队列已满且正在运行的线程数量小于最大线程数(maximumPoolSize),则会创建非核心线程来执行任务。
- 这里需要注意,是先执行新的任务,队列里的任务不会执行,详见:5. 注意事项
- 如果队列已满且正在运行的线程数量已达到最大线程数,且拒绝策略允许,那么线程池会启动拒绝策略来处理新任务。
-
当一个线程完成任务时,它会从队列中取下一个任务来执行,或者在没有任务的情况下进入等待状态。
-
当一个线程空闲时间超过设定的keepAliveTime时,线程池会根据以下判断来决定线程的命运:
- 如果当前运行的线程数大于核心线程数(corePoolSize),则空闲线程会被终止。
- 线程池的所有任务完成后,它最终会收缩到核心线程数的大小。
-
注意事项:
在Java中java.util.concurrent.ThreadPoolExecutor线程池的默认行为是,当任务队列已满且再来一个新任务时,创建的新线程会被用来执行新来的任务而不是队列里已有的任务。
-
线程工作原理示意图:
3. 自定义线程池
a. 介绍:
前面提到过,一般在工作中都是根据业务场景进行自定义线程池;西面是阿里巴巴开发手册的说明;
b. 实现:
实现代码如下:
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.*;/*** @author xxx* @version 1.0* @date xxx*/@Configuration
public class ThreadPoolExecutorConfig {@Beanpublic ThreadPoolExecutor threadPoolExecutor() {// 创建自定义线程池int corePoolSize = 2; // 核心线程数int maxPoolSize = 4; // 最大线程数long keepAliveTime = 10; // 线程空闲时间TimeUnit unit = TimeUnit.SECONDS; // 时间单位BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10); // 任务队列ThreadFactory threadFactory = Executors.defaultThreadFactory(); // 线程工厂RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); // 拒绝策略// 创建ThreadPoolExecutor对象ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,unit,workQueue,threadFactory,handler);return threadPool;}
}
4. 线程池参数的选择原则
仅供参考:具体的线程池参数,需要根据业务场景,进行合理的测试选择
一般原则:
在使用java.util.concurrent.ThreadPoolExecutor自定义线程池时,参数的设置需要根据具体的业务场景和需求进行调整。以下是一些常用的业务场景和设置原则:
-
短时任务场景:
corePoolSize (n+1):可以设置较小的值,例如CPU核心数加1。
maximumPoolSize (2n):根据系统负载情况和任务的短时性来设置。通常可以设置为核心线程数的两倍或者根据系统资源进行调整。
workQueue:可以选择容量较小的队列,例如SynchronousQueue,以避免任务积压。 -
长时任务场景:
corePoolSize:可以设置为一个相对较大的值,以确保有足够的线程处理任务。
maximumPoolSize:根据系统负载和任务的长时性来设置。如果长时任务较多,可以将最大线程数设置得较大一些。
keepAliveTime 和 TimeUnit:根据任务的处理时长和系统的响应时间来设置空闲线程的存活时间。 -
I/O密集型任务场景:
corePoolSize(2n):可以设置为较大的值,以充分利用系统资源,加速I/O操作。
maximumPoolSize:根据系统负载和I/O操作的并发数来设置,可以设置得比较大以应对高并发的情况。
workQueue:可以选择一个适当大小的队列,以充分缓冲I/O任务,但不至于占用过多内存。 -
CPU密集型任务场景:
corePoolSize:可以根据CPU核心数设置,以充分利用系统的多核处理能力。
maximumPoolSize:可以设置得比较大,以应对突发的CPU密集型任务,但不要超过系统负载的承受范围。
workQueue:选择一个合适大小的队列来缓冲任务,避免因任务积压导致性能下降。
设置原则:
要根据具体的业务需求和系统特点来选择参数。
要根据实际情况进行监控和调优,以确保线程池能够有效地处理任务并保持系统的稳定性和性能。
要平衡资源的利用和系统的响应能力,避免设置过大或过小的参数,导致资源浪费或性能问题。
相关文章:

ThreadPool-线程池使用及原理
1. 线程池使用方式 示例代码: // 一池N线程 Executors.newFixedThreadPool(int) // 一个任务一个任务执行,一池一线程 Executors.newSingleThreadExecutorO // 线程池根据需求创建线程,可扩容,遇强则强 Executors.newCachedThre…...
高性能服务系列【十一】主题匹配
主题匹配核心算法就是字符串匹配,在字符串匹配基础上,会加入分段匹配需求,类似URL的点分式字符串。这个算法在几个场景中十分普遍。 1、应用层的路由寻址。比如反向代理中,根据请求中的URL,转发到对应的后台服务。 2…...

Vue 2 组件发布到 npm 的常见问题解决
按照 Vue 2 组件打包并发布到 npm 的方法配置项目后,项目在实际开发过程中,随着代码写法的多样性增加而遇到的各种打包问题,本文将予以逐一解决: 本文目录 同时导出多个组件 样式表 import 问题解决 Json 文件 import 问题解决…...
p2p原理
p2p原理 P2P (Peer-to-Peer) 是一种分布式计算和网络架构模型,它允许对等节点之间直接通信和共享资源,而无需通过集中的服务器。P2P 原理的核心概念是平等性(peer equality),即所有节点在网络中都具有相同的功能和能力…...

从供方协议管理到外部供方管理
从GJB 5000A的供方协议管理到GJB 5000B的外部供方管理,军用软件的研制对承接单位有了更高的标准和要求,也对外部供方管理有了更改的要求,让我们看看具体的变化吧! 供方协议管理的目的: 管理供方产品的获取工作。 外部…...

微服务demo(四)nacosfeigngateway
一、gateway使用: 1、集成方法 1.1、pom依赖: 建议:gateway模块的pom不要去继承父工程的pom,父工程的pom依赖太多,极大可能会导致运行报错,新建gateway子工程后,pom父类就采用默认的spring-b…...

2D与动画
2D转换 1.移动 translate 1. 语法 transform: translate(x,y); 或者分开写 transform: translateX(n); transform: translateY(n); 2.重点 定义 2D 转换中的移动,沿着 X 和 Y 轴移动元素 translate最大的优点:不会影响到其他元素的位置 translat…...
Maven:构建现代化软件项目的强大工具
在软件开发的世界中,Maven 是一个备受欢迎的构建工具。它提供了一种标准化、自动化的方式来管理项目的依赖、构建过程和部署。本文将深入探讨 Maven 的各个方面,帮助您更好地理解和使用这一强大的工具。 一、Maven 的简介 Maven 是一个基于项目…...
脏牛提权(靶机复现)
目录 一、脏牛漏洞概述 二、漏洞复现 1.nmap信息收集 1.1.查看当前IP地址 1.2.扫描当前网段,找出目标机器 1.3.快速扫描目标机全端口 三、访问收集到的资产 192.168.40.134:80 192.168.40.134:1898 四、msf攻击 1.查找对应exp 2.选择对应exp并配置相关设置 五、内…...

用html写一个贪吃蛇游戏
<!DOCTYPE html> <html> <head><title>贪吃蛇</title><meta charset"UTF-8"><meta name"keywords" content"贪吃蛇"><meta name"Description" content"这是一个初学者用来学习的小…...

Topaz Gigapixel AI for Mac 图像放大软件
Topaz Gigapixel AI for Mac是一款专为Mac用户设计的智能图像放大软件。它采用了人工智能技术,特别是深度学习算法,以提高图像的分辨率和质量,使得图像在放大后仍能保持清晰的细节。这款软件的特点在于其能够将低分辨率的图片放大至高分辨率&…...
uniapp先显示提示消息再返回上一页
一、描述 在有些业务场景中,需要先弹出提示后,再返回上一页。 二、思路 使用定时器,先弹出提示消息,然后开个定时器俩秒后再执行,返回上一页的操作,并且清除定时器。 三、实现 uni.showToast({title: …...

【爬虫开发】爬虫从0到1全知识md笔记第2篇:requests模块,知识点:【附代码文档】
爬虫开发从0到1全知识教程完整教程(附代码资料)主要内容讲述:爬虫课程概要,爬虫基础爬虫概述,,http协议复习。requests模块,requests模块1. requests模块介绍,2. response响应对象,3. requests模块发送请求,4. request…...
【算法刷题day11】Leetcode: 20. 有效的括号、 1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值
20. 有效的括号 文档链接:[代码随想录] 题目链接:20. 有效的括号 状态:ok 题目: 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符…...

推荐算法策略需求-rank model优化
1.pred_oobe (base) [rusxx]$ pwd /home/disk2/data/xx/icode/baidu/oxygen/rus-pipeline/pipeline-migrate/UserBaseActiveStatPipeline/his_session (base) [rusxx]$ sh test.sh 2. user_skill_history_dict_expt2包含userid [workxx]$ vim /home/work/xx/du-rus/du_rus_o…...
hadoop 常用命令
hadoop 常用命令 hadoop fs -mkdir /test hadoop fs -put /opt/frank/tb_test03.txt /test/ hadoop fs -ls /test/ hadoop fs -cat /test/tb_test03.txt hadoop fs -rm /test/tb_test03.txt hadoop dfs 也能使用、但不推荐,执行会提示: DEPRECATED: Us…...

pdf在浏览器上无法正常加载的问题
一、背景 觉得很有意思给大家分享一下。事情是这样的,开发给我反馈说,线上环境接口请求展示pdf异常,此时碰巧我前不久正好在ingress前加了一层nginx,恰逢此时内心五谷杂陈,思路第一时间便放在了改动项。捣鼓了好久无果…...

实时语音识别(Python+HTML实战)
项目下载地址:FunASR 1 安装库文件 项目提示所需要下载的库文件:pip install -U funasr 和 pip install modelscope 运行过程中,我发现还需要下载以下库文件才能正常运行: 下载:pip install websockets,pi…...
x86_64 ubuntu22.04编译MetaRTC
metaRTC5.0 API https://github.com/metartc/metaRTC/wiki/metaRTC5.0-API Sample https://github.com/metartc/metaRTC/wiki/metaRTC5.0-API-Sample MetaRTC7.0编译 https://github.com/metartc/metaRTC/wiki/Here-we-come,-write-a-C-version-of-webRTC-that-runs-everywhere…...

FreeRTOS day1
1.总结keil5下载代码和编译代码需要注意的事项 需要与板子连通 配置完成后才点击下载 2.总结STM32Cubemx的使用方法和需要注意的事项 下载支持包 打开芯片配置界面 3.总结STM32Cubemx配置GPIO的方法...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...