线程池及其底层工作原理

一、线程池是什么

线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用 new 线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率在 JDK 的 java.util.concurrent.Executors 中提供了生成多种线程池的静态方法。
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4);
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(4);
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
然后调用他们的 execute 方法即可。
这 4 种线程池底层 全部是 ThreadPoolExecutor 对象的实现, 阿里规范手册中规定
线程池采用 ThreadPoolExecutor 自定义的,实际开发也是。
1. newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若
无可回收,则新建线程。这种类型的线程池特点是:
工作线程的创建数量几乎没有限制(其实也有限制的,数目为 Interger.
MAX_VALUE), 这样可灵活的往线程池中添加线程。
如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为
1 分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程
池重新创建一个工作线程。
在使用 CachedThreadPool 时,一定要注意控制任务的数量,否则,由于大量线
程同时运行,很有会造成系统瘫痪。
2. newFixedThreadPool
创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如 果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
FixedThreadPool 是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。
3. newSingleThreadExecutor
创建一个单线程化的 Executor,即只创建唯一的工作者线程来执行任务,它只会 用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级) 执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是 活动的。
4. newScheduleThreadPool
创建一个定长的线程池,而且支持定时的以及周期性的任务执行。例如延迟 3 秒执行。

二、为什么要使用线程池?

1. 线程池做的工作主要是控制运行的线程数量,处理过程中将任务放入队列,然后 在线程创建后启动这些任务,如果线程数量超过了最 大数量,超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行。
2. 主要特点:线程复用;控制最大并发数:管理线程。
第一:降低资源消耗。通过重复利用己创建的线程降低线程创建和销毁造成的消 耗。
第二:提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执 行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系 统资源,还会降低系统的稳定性,使用线程池可以进 行统一的分配,调优和监控

三、线程池的工作原理

1. 第一步:线程池刚创建的时候,里面没有任何线程,等到有任务过来的时候才会 创建线程。当然也可以调用 prestartAllCoreThreads() 或者 prestartCoreThread() 方法预创建 corePoolSize 个线程
2. 第二步:调用 execute()提交一个任务时,如果 当前的工作线程数 < corePoolSize,直接创建新的线程执行这个任务
3. 第三步:如果 当时工作线程数量 >= corePoolSize,会将任务放入任务队列中缓存
4. 第四步:如果队列已满,并且 线程池中工作线程的数量 < maximumPoolSize,还是会创建线程执行这个任务
5. 第五步:如果队列已满,并且线程池中的线程已达到 maximumPoolSize,这个时候会执行拒绝策略,JAVA 线程池默认的策略是 AbortPolicy,即抛出 RejectedExecutionException 异常
线程池状态
1. **RUNNING(运行中)**:线程池处于正常运行状态,可以接受新任务并处理已 提交的任务。
2. **SHUTDOWN(关闭中)**: 线程池不再接受新任务 但会继续处理已提交的任 务 ,直到任务队列为空。`shutdown()`方法用于将线程池状态切换为 SHUTDOWN。
3. **STOP(停止中)**: 线程池不再接受新任务,并且会尝试终止正在执行的任务。 已提交但未执行的任务会从队列中移除 。`shutdownNow()`方法用于将线程池状态切 换为 STOP。
4. **TIDYING(整理中)**:线程池在 SHUTDOWN 或 STOP 状态下,当所有任务 都已经终止,工作线程数为 0 时,会将线程池状态切换为 TIDYING,表示线程池正在 进行一些清理工作。
5. **TERMINATED(终止)**:线程池的终止状态,表示线 程池已经完全终止 ,不再 处理任务。线程池状态会在 TIDYING 状态结束后切换到 TERMINATED。

四、ThreadPoolExecutor 对象 参数

参数与作用:

        共 7 个参数
1. corePoolSize: 核心线程数,
在 ThreadPoolExecutor 中有一个与它相关的配置:allowCoreThreadTimeOut (默认为 false),当 allowCoreThreadTimeOut 为 false 时,核心线程会一直存 活,哪怕是一直空闲着。而当 allowCoreThreadTimeOut 为 true 时核心线程空 闲时间超过 keepAliveTime 时会被回收。
2. maximumPoolSize:最大线程数线程池能容纳的最大线程数,当线程池中的线程达到最大时,此时添加任务将会采用拒绝策略,默认的拒绝策略是抛出一个运行时错误 (RejectedExecutionException)。
值得一提的是,当初始化时用的工作队列为 LinkedBlockingDeque 时,这个值将无效。
3. keepAliveTime:存活时间, 当非核心空闲超过这个时间将被回收,同时空闲核心线程是否回收受 allowCoreThreadTimeOut 影响。
4. unit: keepAliveTime 的单位。
5. workQueue: 任务队列
常用有三种队列, SynchronousQueue,LinkedBlockingDeque(无界队列),ArrayBlockingQueue(有界队列)。
6. threadFactory: 线程工厂,
ThreadFactory 是一个接口,用来创建 worker。通过线程工厂可以对线程的一些属性进行定制。默认直接新建线程。
7. RejectedExecutionHandler: 拒绝策略
也是一个接口,只有一个方法,当线程池中的资源已经全部使用,添加新线程被拒绝时,会调用 RejectedExecutionHandler 的 rejectedExecution()方法。默认是抛出 一个运行时异常

拒绝策略:

1. AbortPolicy:直接抛出异常,默认策略;
2. CallerRunsPolicy:用调用者所在的线程来执行任务;
3. DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
4. DiscardPolicy:直接丢弃任务;当然也可以根据应用场景实现RejectedExecutionHandler 接口,自定义饱和策略,如记录日志或持久化存储不能 处理的任务

线程池大小设置

        CPU 密集型:N+1                
        IO 密集型:2N
1. 需要分析线程池执行的任务的特性: CPU 密集型还是 IO 密集型
2. 每个任务执行的平均时长大概是多少,这个任务的执行时长可能还跟任务处理逻 辑是否涉及到网络传输以及底层系统资源依赖有关系。 如果是 CPU 密集型,主要是执行计算任务,响应时间很快,cpu 一直在运行, 这种任务 cpu 的利用率很高,那么线程数的配置应该根据 CPU 核心数来决定, CPU 核心数=最大同时执行线程数,加入 CPU 核心数为 4,那么服务器最多能 同时执行 4 个线程。过多的线程会导致上下文切换反而使得效率降低。那线程池的最大线程数可以配置为 cpu 核心数+1 如果是 IO 密集型,主要是进行 IO 操 作,执行 IO 操作的时间较长,这是 cpu 出于空闲状态,导致 cpu 的利用率不 高,这种情况下可以增加线程池的大小。这种情况下可以结合线程的等待时长来做判断,等待时间越高,那么线程数也相对越多。一般可以配置 cpu 核心数的 2 倍。
一个公式:
线程池设定最佳线程数目 =
         ((线程池设定的线程等待时间+线程 CPU 时间) / 线程 CPU 时间 ) * CPU 数目
这个公式的  '线程 cpu 时间'  是预估的程序单个线程在 cpu 上运行的时间(通常使用 loadrunner 测试大量运行次数求出平均值)

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

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

相关文章

分页stater

自定义aop,以添加注解的方法为切入点&#xff0c;对目标方法做一层增强 PageXAop代码如下&#xff1a; package cn.smart.pagex.aop;import com.github.pagehelper.PageHelper; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.a…

漏洞复现 | Showdoc反序列化

非常简单的一个靶场 靶场地址&#xff1a;https://hack.zkaq.cn/ 打开靶场&#xff0c;弹出了这种登录框&#xff0c;这也成为了后面的一个坑点&#xff0c;记住这个登录框。 看到了注册功能&#xff0c;showdoc有注册功能我们就不用尝试前台SQL注入了&#xff0c;直接注册…

Verilog基础:简单标识符和转义标识符

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 标识符(identifier)是一个为了引用而给一个对象起的名字。一个标识符可以是一个简单标识符&#xff0c;也可以是一个转义标识符。本文将对两者进行详细阐述。 简…

Nuxt.js 错误侦探:useError 组合函数

title: Nuxt.js 错误侦探&#xff1a;useError 组合函数 date: 2024/7/14 updated: 2024/7/14 author: cmdragon excerpt: 摘要&#xff1a;文章介绍Nuxt.js中的useError组合函数&#xff0c;用于统一处理客户端和服务器端的错误&#xff0c;提供statusCode、statusMessage和…

【C++】—— 初识C++

【C】—— 初识C 一、什么是 C二、C 的发展历史三、C 版本更新四、C 的重要性五、C 在工作领域中的运用六、C 书籍推荐&#xff1a; 一、什么是 C C语言 是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要…

k8s快速部署一个网站

1&#xff09;使用Deployment控制器部署镜像&#xff1a; kubectl create deployment web-demo --imagelizhenliang/web-demo:v1 kubectl get deployment,pods[rootk8s-matser ~]# kubectl get pods NAME READY STATUS RESTARTS A…

STM32 BootLoader 刷新项目 (四) 通信协议

STM32 BootLoader 刷新项目 (四) 通信协议 文章目录 STM32 BootLoader 刷新项目 (四) 通信协议1. 通信流程2. 支持指令3. 通信流程4. 指令结构5. 操作演示 前面几章节&#xff0c;我们已经介绍了BootLoader的整体程序框架&#xff0c;方案设计&#xff0c;以及STM32CubdeMX的配…

数据结构(4.0)——串的定义和基本操作

串的定义(逻辑结构) 串&#xff0c;即字符串(String)是由零个或多个字符组成的有序数列。 一般记为Sa1a2....an(n>0) 其中&#xff0c;S是串名&#xff0c;单引号括起来的字符序列是串的值;ai可以是字母、数字或其他字符&#xff1b;串中字符的个数n称为串的长度。n0时的…

常开常闭液位传感器怎么选

在选择常开常闭传感器时&#xff0c;关键是根据其工作原理和应用需求来进行合适的选择&#xff0c;以确保系统的正常运行和效率。常开和常闭传感器的设计在信号输出时有明显差异&#xff0c;因此在不同的控制系统中选择合适的类型至关重要。 常开传感器的特点是在没有检测到目…

Nginx的访问限制与访问控制

访问限制 访问限制是一种防止恶意访问的常用手段&#xff0c;可以指定同一IP地址在固定时间内的访问次数&#xff0c;或者指定同一IP地址在固定时间内建立连接的次数&#xff0c;若超过网站指定的次数访问将不成功。 请求频率限制配置 请求频率限制是限制客户端固定时间内发…

C#小结:未能找到类型或命名空间名“xxx”(是否缺少 using 指令或程序集引用?)

方案一&#xff1a;移除这些失效的引用&#xff0c;下载对应版本的dll&#xff0c;重新添加引用 方案二&#xff1a;项目右键属性-调整目标框架版本&#xff08;一般是降低版本&#xff09; 方案三&#xff1a;调整编译顺序&#xff1a; 项目A&#xff1a;引用1、引用2 &…

鸿蒙架构之AOP

零、主要内容 AOP 简介ArkTs AOP 实现原理 JS 原型链AOP实现原理 AOP的应用场景 统计类&#xff1a; 方法调用次数统计、方法时长统计防御式编程&#xff1a;参数校验代理模式实现 AOP的注意事项 一、AOP简介 对于Android、Java Web 开发者来说&#xff0c; AOP编程思想并不…

最值得推荐的10款Windows软件!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频播放量破百万https://aitools.jurilu.com/1.音乐播放器——Dopamine Dopamine是一款音乐播放器&#xff0c;设计简洁美观。它支持多种音频格式&#xff0c;包括wav、mp3、ogg…

亚马逊IP关联是什么?要怎么解决呢?

亚马逊不仅提供了广泛的商品和服务&#xff0c;也是许多企业和个人选择的电子商务平台。然而&#xff0c;与亚马逊相关的IP关联问题&#xff0c;特别是在网络安全和运营管理方面&#xff0c;经常成为使用亚马逊服务的用户和商家关注的焦点。通过了解亚马逊IP关联的含义、可能的…

MMLab-dataset_analysis

数据分析工具 这里写目录标题 数据分析工具dataset_analysis.py数据可视化分析 benchmark.pybrowse_coco_json.pybrowse_dataset.pyOptimize_anchors mmyolo、mmsegmentation等提供了数据集分析工具 dataset_analysis.py 数据采用coco格式数据 根据配置文件分析全部数据类型或…

pico+unity手柄和摄像机控制初级设置

1、摄像头配置 摄像头模式、floor是追踪原点类型&#xff08;将根据设备检测到地面的高度来计算追踪原点&#xff09;&#xff0c; Device 模式时&#xff0c;为通常理解的 Eye 模式&#xff0c;不会将根据设备检测到地面的高度来计算追踪原点 选择floor时&#xff0c;修改相…

K8S ingress 初体验 - ingress-ngnix 的安装与使用

准备环境 先把 google 的vm 跑起来… gatemanMoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-user$ kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane,master 124d v1.23.6 k8s-no…

王牌站士Ⅶ--理解大型语言模型LLM的参数

模型的大小并不一定决定其成功 在学习任何大型语言模型 (LLM) 时&#xff0c;您首先会听到的事情之一就是给定模型有多少个参数。如果您查看下面的图表&#xff0c;您会注意到参数大小范围很广 - 一个模型可能有 10 亿或 20 亿个参数&#xff0c;也可能有超过 1.75 万亿个参数。…

了解redis

1.什么是redis&#xff1f; redis是一款高性能的NOSQL系列的非关系型数据库 想了解非关系型数据库概念前往上期(NoSQL Not Only SQL)&#xff0c;意即“不仅仅是SQL”-CSDN博客 Redis是用C语言开发的一个开源的高性能键值对&#xff08;key-value&#xff09;数据库&#x…

CentOS7.X系统部署Zabbix6.0版本(可跟做)

文章目录 一、部署环境说明二、基本环境部署步骤1、环境初始化操作2、部署并配置Nginx3、部署并配置PHP4、测试NginxPHP环境5、部署并配置MariaDB 三、Zabbix-Server部署步骤1、编译安装Zabbix-Server2、导入Zabbix初始化库3、配置Zabbix前端UI4、启动Zabbix-Server5、WEB页面配…