一文搞懂 java 线程池:ThreadPoolExecutor 和 FixedThreadPool 原理

你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益:

  1. 了解大厂经验
  2. 拥有和大厂相匹配的技术等

希望看什么,评论或者私信告诉我!

文章目录

  • 一、前言
  • 二、线程池原理
    • 2.1 ThreadPoolExecutor 原理
    • 2.2 ThreadPoolExecutor的 execute 方法原理
    • 2.3 FixedThreadPool
      • 2.3.1 FixedThreadPool 简介
      • 2.3.2 FixedThreadPool 的 execute 方法原理
      • 2.3.2 FixedThreadPool 优缺点及应用场景
  • 三、总结

一、前言

上一章节我们详解介绍了线程池的一些关键性知识。这章我们会详细介绍各个线程池的原理

二、线程池原理

2.1 ThreadPoolExecutor 原理

从图中可以看出,当提交一个新任务到线程池时,线程池的处理流程如下。

  1. 线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。
  2. 线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
  3. 线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务

2.2 ThreadPoolExecutor的 execute 方法原理

ThreadPoolExecutor执行execute方法分下面4种情况。

  1. 如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步骤需要获取全局锁)。
  2. 如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue。
  3. 如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务(注意,执行这一步骤需要获取全局锁)。
  4. 如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用RejectedExecutionHandler.rejectedExecution()方法。

ThreadPoolExecutor采取上述步骤的总体设计思路,是为了在执行execute()方法时,尽可能地避免获取全局锁(那将会是一个严重的可伸缩瓶颈)。在ThreadPoolExecutor完成预热之后(当前运行的线程数大于等于corePoolSize),几乎所有的execute()方法调用都是执行步骤2,而步骤2不需要获取全局锁。

2.3 FixedThreadPool

2.3.1 FixedThreadPool 简介

FixedThreadPool被称为可重用固定线程数的线程池,通过上一篇我们知道它是通过 ThreadPoolExecutor 来实现的,下面是FixedThreadPool的源代码实现。

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

FixedThreadPool的corePoolSize和maximumPoolSize都被设置为创建FixedThreadPool时指定的参数nThreads。

当线程池中的线程数大于corePoolSize时,keepAliveTime为多余的空闲线程等待新任务的最长时间,超过这个时间后多余的线程将被终止。这里把keepAliveTime设置为0L,意味着多余的空闲线程会被立即终止

2.3.2 FixedThreadPool 的 execute 方法原理

  1. 如果当前运行的线程数少于corePoolSize,则创建新线程来执行任务。
  2. 在线程池完成预热之后(当前运行的线程数等于corePoolSize),将任务加入LinkedBlockingQueue。
  3. 线程执行完1中的任务后,会在循环中反复从LinkedBlockingQueue获取任务来执行。FixedThreadPool使用无界队列LinkedBlockingQueue作为线程池的工作队列(队列的容量为Integer.MAX_VALUE)。

使用无界队列作为工作队列会对线程池带来如下影响。

  1. 当线程池中的线程数达到corePoolSize后,新任务将在无界队列中等待,因此线程池中的线程数不会超过corePoolSize。
  2. 由于1,使用无界队列时maximumPoolSize将是一个无效参数。
  3. 由于1和2,使用无界队列时keepAliveTime将是一个无效参数。
  4. 由于使用无界队列,运行中的FixedThreadPool(未执行方法shutdown()或shutdownNow())不会拒绝任务(不会调用RejectedExecutionHandler.rejectedExecution方法)

2.3.2 FixedThreadPool 优缺点及应用场景

FixedThreadPool 是一个固定大小的线程池,在实际应用中有一些适合的场景和优点:

适用场景:

  1. 资源管理:FixedThreadPool 适合于资源受限的情况,因为它可以限制并发线程的数量,避免资源耗尽或者系统负载过高。
  2. 任务一致性:适合执行一组数量固定的相同类型或相似类型的任务,这样可以保持线程池中的线程数量恒定。
  3. 控制并发度:适合于需要限制并发度的场景,比如执行文件处理、网络请求或数据库操作,以避免并发线程过多而导致性能下降。
  4. 简单任务:适合于执行较为简单的短时任务,因为固定大小的线程池可以降低线程的创建和销毁开销。
  5. 避免资源竞争:适合于避免因为线程数量过多导致资源竞争和线程调度开销较大的情况。

优点:

  1. 固定线程数:FixedThreadPool 的线程数量固定,可以更好地控制系统的并发度,避免过多的线程导致资源消耗和线程调度开销。
  2. 资源管理:对于有限的资源环境,在 ThreadPool 中固定线程数可以更好地管理资源,避免资源耗尽问题。
  3. 优化性能:固定大小的线程池可以避免线程创建和销毁的开销,对于执行频繁的任务能够提升性能。
  4. 任务排队:当任务数量大于线程池大小时,FixedThreadPool 中的任务会被放入队列中等待执行,保证任务不会丢失。

示例场景:

  • Web 服务器中处理请求:对于固定数量的请求处理器线程池,能够控制同时处理请求数量,避免处理请求的过度延迟。
  • 数据库查询:限制并发的数据库查询线程数量,避免数据库连接过度消耗。
  • 后台任务处理:用于处理一些耗时任务,比如定时检查或清理任务。
  • 池化资源管理:对于有限数量的资源如连接池、线程池等管理。

FixedThreadPool 的固定线程数量能够让你更好地控制系统资源的分配和线程的使用,适用于一些需求稳定并且相对简单的线程管理场景。

三、总结

文章深入解析了Java中线程池的核心工作机制,重点阐释了ThreadPoolExecutor如何管理线程和任务,以及FixedThreadPool在实际应用中的适用场景、优点和局限性。通过具体源代码和执行流程分析,让读者对线程池的实现原理有了清晰的认识。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux——shell原理和文件权限

1.shell原理 在我们使用云服务器时&#xff0c;需要通过shell进行使用&#xff0c;而shell则是一种外壳程序。 我们提到过&#xff0c;大部分的指令实际上就是文件&#xff0c;当用户需要执行某种功能时&#xff0c;由于用户不擅长和操作系统直接交互&#xff08;操作复杂&…

k8s部署单机版mysql8

一、创建命名空间 # cat mysql8-namespace.yaml apiVersion: v1 kind: Namespace metadata:name: mysql8labels:name: mysql8# kubectl apply -f mysql8-namespace.yaml namespace/mysql8 created# kubectl get ns|grep mysql8 mysql8 Active 8s二、创建mysql配…

论文学习——使用基于多项式拟合的预测算法求解动态多目标问题

论文题目&#xff1a;Solving dynamic multi-objective problems using polynomial fitting-based prediction algorithm 使用基于多项式拟合的预测算法求解动态多目标问题&#xff08;Qingyang Zhang , Xiangyu He,Shengxiang Yang , Yongquan Dong , Hui Song , Shouyong Ji…

配置WLAN 示例

规格 仅AR129CVW、AR129CGVW-L、AR109W、AR109GW-L、AR161W、AR161EW、AR161FGW-L、AR161FW、AR169FVW、AR169JFVW-4B4S、AR169JFVW-2S、AR169EGW-L、AR169EW、AR169FGW-L、AR169W-P-M9、AR1220EVW和AR301W支持WLAN-FAT AP功能。 组网需求 如图1所示&#xff0c;企业使用WLAN…

JDeveloper 12C 官网下载教程

首先、我们要登录Oracle官网 Oracle 甲骨文中国 | 云应用和云平台 登录进去如果不是中文可以点击右上角带有国旗的图标就行更改&#xff0c;选择一个你能看懂的文字。 然后&#xff0c;点击“资源”—点击“开发人员下载” 然后&#xff0c;点击“开发工具” 这里有很多工具可…

【设计模式】【行为型模式】【责任链模式】

系列文章目录 可跳转到下面链接查看下表所有内容https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501文章浏览阅读2次。系列文章大全https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501 目录…

Python协作运动机器人刚体力学解耦模型

&#x1f3af;要点 &#x1f3af;腿式或固定式机器人模型 | &#x1f3af;网格、点云和体素网格碰撞检测 | &#x1f3af;正反向运动学和动力学 | &#x1f3af;机器人刚体力学计算 | &#x1f3af;编辑参考系姿势和路径 | &#x1f3af;软件接口实体机器人模拟 | &#x1f3a…

奇葩公司又发微博了,网友表示“乐”

多益网络 近日&#xff0c;多益网络官方微博发帖&#xff0c;公然表示对法院仲裁结果不服&#xff0c;认为劳动法有极多问题。 大家不要看微博内容似乎振振有词&#xff0c;极有可能只是多益网络单方面的选择性表达&#xff0c;毕竟多益网络的臭名早就家喻户晓。 况且对前员工直…

车载资料分享中:硬件在环、canoe、UDS诊断、OTA升级、TBOX测试

每日直播时间&#xff1a; 周一到周五&#xff1a;20&#xff1a;00-23&#xff1a;00 周六与周日&#xff1a;9&#xff1a;00-17&#xff1a;00 直播内容&#xff1a;&#xff08;车厂一比一测试&#xff09; HIL&#xff08;硬件在环&#xff09;测试、UDS功能诊断、UDS自动…

一首歌的时间 写成永远

大家好&#xff0c;我是秋意零。 就在&#xff0c;2024年6月20日。我本科毕业了&#xff0c;之前专科毕业挺有感触&#xff0c;也写了一篇文章进行记录。如今又毕业了&#xff0c;还是写一篇文章记录吧&#xff01;&#xff01; 专科毕业总结&#xff1a;大学三年总结&#xf…

使用ElementUI组件库

引入ElementUI组件库 1.安装插件 npm i element-ui -S 2.引入组件库 import ElementUI from element-ui; 3.引入全部样式 import element-ui/lib/theme-chalk/index.css; 4.使用 Vue.use(ElementUI); 5.在官网寻找所需样式 饿了么组件官网 我这里以button为例 6.在组件中使用…

利用深度学习模型进行语音障碍自动评估

语音的产生涉及器官的复杂协调&#xff0c;因此&#xff0c;语音包含了有关身体各个方面的信息&#xff0c;从认知状态和心理状态到呼吸条件。近十年来&#xff0c;研究者致力于发现和利用语音生物标志物——即与特定疾病相关的语音特征&#xff0c;用于诊断。随着人工智能&…

电信NR零流量小区处理

【摘要】随着目前网络建设逐步完善&#xff0c;5G用户的不断发展&#xff0c;针对零流量小区的分析及处理存在着必要性&#xff0c;零流量小区的出现既是用户分布及行为的直观体现&#xff0c;也是发展用户的一个指引&#xff0c;同时也能发现设备的一些故障。一个站点的能够带…

飞书API 2-3:如何使用 API 创建数据表,解放人工?

一、引入 作为飞书多维表的深度使用者&#xff0c;经常需要将一些数据库的数据同步到多维表上&#xff0c;在数据写入之前&#xff0c;一般需要新建数据表和字段。当通过网页端界面新建字段时&#xff0c;如果字段少&#xff0c;还能接受手动一个个创建&#xff0c;不过一旦字…

C++字体库开发

建议根据字体需求&#xff0c;多个组合使用。高度定制可基于freeTypeharfbuzz基础库完成。 GitHub - GNOME/pango: Read-only mirror of https://gitlab.gnome.org/GNOME/pango GitHub - googlefonts/fontview: Demo app that displays fonts with a free/libre/open-source …

更好的方法_交叉观察器API

交叉观察器&#xff08;Intersection Observer&#xff09;API 是一个强大的工具&#xff0c;可以用来检测元素是否进入视口或从视口移出。我们可以利用这个 API 来实现粘贴式导航&#xff08;也称为粘性导航&#xff09;&#xff0c;即在用户滚动页面时&#xff0c;导航栏会在…

方法的用法

一.简介 目前为止我给出的所有的案例都是将代码放在main方法中&#xff0c;就会产生一些问题&#xff1a; 代码冗长&#xff0c;不利于维护变量过多&#xff0c;想不出那么多的变量名没有重用性 那么该如何解决呢&#xff1f; 我们可以编写功能性的代码块&#xff0c;来被ma…

Android自动化测试实践:uiautomator2 核心功能与应用指南

Android自动化测试实践&#xff1a;uiautomator2 核心功能与应用指南 uiautomator2 是一个用于Android应用的自动化测试Python库&#xff0c;支持多设备并行测试操作。它提供了丰富的API来模拟用户对App的各种操作&#xff0c;如安装、卸载、启动、停止以及清除应用数据等。此外…

基于索尼基于索尼Spresense的眼睛跟随平台中两个模型的对比

1.模型一(现在使用的) 这个模型是一个简单的神经网络&#xff0c;由三个主要组件组成&#xff1a;输入层、一个全连接层&#xff08;Affine层&#xff09;、一个Sigmoid激活函数层和一个Binary Cross Entropy损失层。 以下是每个组件的说明&#xff1a; Input 层&#xff1a;这…

计算机专业的概念需要拓宽|终身学习之旅利:用FlowUs打造个性化学习记录知识库

计算机相关专业长期以来一直是热门选择&#xff0c;这主要得益于技术的快速发展和广泛的应用场景。随着AI技术的不断进步&#xff0c;这一趋势在未来几年内仍有望持续。以下是从不同角度对这个问题的分析&#xff1a; 从AI发展的角度&#xff1a; 技术革新&#xff1a;AI技术…