【昕宝爸爸小模块】图文源码详解什么是线程池、线程池的底层到底是如何实现的

在这里插入图片描述

➡️博客首页       https://blog.csdn.net/Java_Yangxiaoyuan


       欢迎优秀的你👍点赞、🗂️收藏、加❤️关注哦。


       本文章CSDN首发,欢迎转载,要注明出处哦!


       先感谢优秀的你能认真的看完本文,有问题欢迎评论区交流,都会认真回复!


图文源码详解什么是线程池、线程池的底层到底是如何实现的

  • 一、✅引言
    • 1.1✅典型解析
    • 1.2✅线程池什么情况下使用
    • 1.3✅线程池的优缺点
  • 二、✅拓展知识仓
    • 2.1✅线程池的实现原理
    • 2.2✅添加一个任务
    • 2.3✅添加worker线程
    • 2.4✅worker线程处理队列任务
  • 三、✅总结
    • 3.1✅线程池参数
    • 3.2✅Executors
    • 3.3✅线程池相关


一、✅引言


1.1✅典型解析


线程池是池化技术的一种典型实现,所谓池化技术就是提前保存大量的资源,以备不时之需。在机器资源有限的情况下,使用池化技术可以大大的提高资源的利用率,提升性能等。


线程池,说的就是提前创建好一批线程,然后保存在线程池中,当有任务需要执行的时候,从线程池中选一个线程来执行任务。


在编程领域,比较典型的池化技术有:


线程池、连接池、内存池、对象池等


Java中线程池的继承关系如下:


在这里插入图片描述


1.2✅线程池什么情况下使用


线程池适合在以下情况下使用


1. 有大量短时间任务需要处理。如果每个任务都单独开一个线程,那么线程的创建、销毁与切换会消耗相当多的资源,而线程池可以重用已有的线程,从而减少这些开销。


2. 需要管理多个任务的执行顺序。线程池可以根据任务的优先级或提交时间等因素来调度任务的执行,从而更加稳定和可控。


3. 需要限制并发执行的任务数量。通过设置线程池的最大线程数量,可以保证同时执行的任务数不会超过设定值,从而避免系统资源被过度占用。


4. 需要异步执行任务,并获取任务的执行结果。线程池可以通过返回std::future对象来实现异步执行任务,并在需要时获取任务的执行结果。


5. 并发任务处理:线程池可以用于处理并发的任务,例如处理请求、批量处理数据、并行计算等。通过线程池,可以管理和复用线程,提高任务的执行效率。


6. 异步任务执行:线程池可以用于执行异步任务,将任务提交给线程池后,可以立即返回并继续执行后续代码,不必等待任务完成。适用于需要在后台执行耗时任务,同时不阻塞主线程的场景。


1.3✅线程池的优缺点


线程池是一种用于管理线程的机制,它可以在程序运行时创建一定数量的线程,并将这些线程放入线程池中以供复用。线程池可以有效地减少线程的创建和销毁开销,提高系统的性能和响应速度。下面是一些线程池的优缺点:


优点


  1. 降低资源消耗:线程池中的线程可以重复利用,避免了频繁地创建和销毁线程,从而降低了系统的开销。
  2. 提高响应速度:线程池可以预先创建一定数量的线程,当任务到达时可以直接使用这些线程,无需等待线程的创建,提高了系统的响应速度。
  3. 提高线程的可管理性:线程池可以进行统一的分配、调优和监控,方便对线程的管理和维护。
  4. 控制并发数:线程池可以限制任务的并发执行数量,避免了过多的线程导致系统资源的耗尽。
  5. 提供任务队列:线程池可以配合任务队列使用,缓冲尚未执行的任务,避免了任务因为线程不够而被拒绝执行的情况。

缺点


  1. 无法充分利用多核资源:由于线程数量有限,当线程数量过多时,可能会浪费系统资源,并且无法充分利用多核资源。
  2. 无法适应动态负载变化:线程池中的线程数量是固定的,因此在面对任务负载的动态变化时,线程池可能无法做到自适应调整。
  3. 无法处理无限制创建线程的情况:虽然线程池可以限制任务的并发数,但是如果程序中出现无限制创建线程的情况,线程池也无法解决该问题。
  4. 维护成本较高:如果线程池的大小设置不当或者调优不当,可能会导致系统性能的下降或者资源的浪费,需要进行相应的调整和维护。

二、✅拓展知识仓


2.1✅线程池的实现原理


通常,一般构造函数会反映出这个工具或这个对象的数据存储结构。


在这里插入图片描述

如果把线程池比作一个公司。公司会有正式员工处理正常业务,如果工作量大的话,会雇佣外包人来工作。




闲时就可以释放外包人员以减少公司管理开销。一个公司因为成本关系,雇佣的人员始终是有最大数。




如果这时候还有任务处理不过来,就走需求池排任务。


  1. acc: 获取调用上下文
  2. corePoolSize: 核心线程数量,可以类比正式员工数量,常驻线程数量
  3. maximumPoolSize: 最大的线程数量,公司最多雇佣员工数量。常驻+临时线程数量
  4. workQueue: 多余任务等待队列,再多的人都处理不过来了,需要等着,在这个地方等
  5. keepAliveTime: 非核心线程空闲时间,就是外包人员等了多久,如果还没有活干,解雇了
  6. threadFactory:创建线程的工厂,在这个地方可以统一处理创建的线程的属性。每个公司对员工的要求不一样,恩,在这里设置员工的属性。
  7. handler: 线程池拒绝策略,什么意思呢? 就是当任务实在是太多,人也不够,需求池也排满了还有任务咋办?默认是不处理,抛出异常告诉任务提交者,我这忙不过来了

2.2✅添加一个任务


接着,我们看一下线程池中比较重要的execute方法,该方法用于向线程池中添加一个任务。


在这里插入图片描述

核心模块用红框标记了:


  • 第一个红框: workerCount0f万法根据tl的低29位,得到线程池的当前线程数,如果线程数小于corePoolSize,则执行addWorker方法创建新的线程执行任务。

  • 第二个黄框:判断线程池是否在运行,如果在,任务队列是否允许插入,插入成功再次验证线程池是否运行,如果不在运行,移除插入的任务,然后抛出拒绝策略。如果在运行,没有线程了,就启用一个线程。

  • 第三个黄框: 如果添加非核心线程失败,就直接拒绝了。

这里逻辑稍微有点复杂,画了个流程图仅供参考:


在这里插入图片描述

接下来,我们看看如何添加一个工作线程的?


2.3✅添加worker线程


从方法 execute 的实现可以看出: addWorker 主要负责创建新的线程并执行任务,代码如下(这里代码有点长,没关系,也是分块的,总共有5个关键的代码块) :


在这里插入图片描述

  • 第一个红框 : 做是否能够添加工作线程条件过滤:

判断线程池的状态,如果线程池的状态值大于或等 SHUTDOWN,则不处理提交的任务,直接返回;


  • 第二个红框:做自旋,更新创建线程数量:

通过参数 core 判断当前需要创建的线程是否为核心线程,如果core为true,且当前线程数小于 corePoolSize ,则跳出循环,开始创建新的线程:


有人或许会疑问 retry 是什么? 这个是iava中的goto语法。只能运用在break和continue后面


接着看后面的代码:


在这里插入图片描述

  • 第一个红框: 获取线程池主锁。

线程池的工作线程通过Woker类实现,通过ReentrantLock锁保证线程安全。


  • 第二个红框: 添加线程到workers中 (线程池中)。
  • 第三个红框: 启动新建的线程。

接下来,我们看看workers是什么。


在这里插入图片描述

一个hashSet。所以,线程池底层的存储结构其实就是一个HashSet。


2.4✅worker线程处理队列任务


在这里插入图片描述

  1. 第一个红框: 是否是第一次执行任务,或者从队列中可以获取到任务。
  2. 第二个红框: 获取到任务后,执行任务开始前操作钩子。
  3. 第三个红框: 执行任务。
  4. 第四个红框: 执行任务后钩子。

这两人钩子 (beforeExecute,afterExecute) 允许我们自己继承线程池,做任务执行前后外理。


到这里,源代码分析到此为止。


三、✅总结


3.1✅线程池参数


通过上面的源码解析我们可以看到,线程池的参数主要包括以下七个:


  1. corePoolSize:线程池中的常驻核心线程数。
  2. maximumPoolSize:线程池能够容纳同时执行的最大线程数。此值必须大于等于1。
  3. keepAliveTime:多余的空闲线程存活时间。当空闲时间达到此值时,多余的线程会被销毁直到只剩下corePoolSize个线程为止。
  4. unit:keepAliveTime的时间单位,如秒、毫秒等。
  5. workQueue:任务队列,被提交但尚未被执行的任务。当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务。
  6. threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程,一般用默认的即可。
  7. handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的数量最大线程数时如何来拒绝请求执行的runnable的策略。

3.2✅Executors


Executors的创建线程池的方法,创建出来的线程池都实现了ExecutorService接口。常用方法有以下几个:


newFixedThreadPool(int Threads): 创建固定数目线程的线程池;


newCachedThreadPool(): 创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60秒钟未被使用的线程。


newSingleThreadExecutor0创建一个单线程化的Executor。


newScheduledThreadPoolint corePoolSize)创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。


3.3✅线程池相关


所谓线程池本质是一个hashSet。多余的任务会放在阻塞队列中。


只有当阻塞队列满了后,才会触发非核心线程的创建。所以非核心线程只是临时过来打杂的。直到空闲了,然后自己关闭了。


线程池提供了两个钩子(beforeExecute,afterExecute) 给我们,我们继承线程池,在执行任务前后做一些事情。


线程池原理关键技术: 锁 (lock,cas)阻塞队列hashSet (资源池)


在这里插入图片描述

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

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

相关文章

发送HTTP POST请求并处理响应

发送HTTP POST请求并处理响应是Web开发中的常见任务。在Go语言中,可以使用net/http包来发送HTTP POST请求并处理响应。 以下是一个示例代码,演示了如何发送HTTP POST请求并处理响应: go复制代码 package main import ( "b…

代码随想录算法训练营day10|232.用栈实现队列、225.用队列实现栈

理论基础 232.用栈实现队列 225. 用队列实现栈 理论基础 了解一下 栈与队列的内部实现机智,文中是以C为例讲解的。 文章讲解:代码随想录 232.用栈实现队列 大家可以先看视频,了解一下模拟的过程,然后写代码会轻松很多。 题目链…

Maven 依赖传递和冲突、继承和聚合

一、依赖传递和冲突 1.1 Maven 依赖传递特性 1.1.1 概念 假如有三个 Maven 项目 A、B 和 C,其中项目 A 依赖 B,项目 B 依赖 C。那么我们可以说 A 依赖 C。也就是说,依赖的关系为:A—>B—>C, 那么我们执行项目 …

性能优化-一文宏观理解OpenCL

本文主要对OpenCL做一个整体的介绍、包括环境搭建、第一个OpenCL程序、架构、优化策略,希望对读者有所收获。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:高性能(HPC)开发基础…

利用 ChatGPT 高效搜索:举一反三的思考方式,高效查找解决方案

文章目录 基础思路举一反三Go 语言 Web 框架延伸思考思考结论 本文只是我的一些尝试,基于 ChatGPT 实现系统化快速搜索某编程语言的特定领域相关包或者基于其他语言类推荐落地方案的尝试。 这篇文章中描述的方式不一定是好方式,但应该会有一定的启示作用…

Autosar --- CRC8 SAE J1850 CRC计算

前言 CRC计算一般用于通信中,用来保证一组数据的完整性。 发送方发送一组数据dataACRC检验码CRCa(CRC校验码由数据算出); 接收方接收到数据dataACRC校验码CRCa,接收方通过与发送方约定好的计算公式,计算出一…

*p++和(*p)++一样吗

大家好,今天给大家介绍*p和(*p)的区别,文章末尾附有分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!可进群免费领取。 *p 和 (*p) 在 C/C 语言中具有不同的含义。 *p:这个表…

Java研学-Maven基础

一 概述 Maven是一个跨平台的项目管理工具,主要用于基于 Java 平台的项目(Maven 底层为Java)构建、依赖包管理和项目信息管理,只需要运行一条简单的命令,就能高效的完成构建动作   Maven 能提供一种项目的依赖配置&a…

精细微调技术在大型预训练模型优化中的应用

目录 前言1 Delta微调简介2 参数微调的有效性2.1 通用知识的激发2.2 高效的优化手段3 Delta微调的类别3.1 增量式微调3.2 指定式微调3.3 重参数化方法 4 统一不同微调方法4.1 整合多种微调方法4.2 动态调整微调策略4.3 超参数搜索和优化 结语 前言 随着大型预训练模型在自然语…

超优秀的三维模型优化平台(轻量化、格式转换、可视化等)

老子云概述 老子云3D可视化快速开发平台,集云压缩、云烘焙、云存储云展示于一体,使3D模型资源自动输出至移动端PC端、Web端,能在多设备、全平台进行展示和交互,是全球领先、自主可控的自动化3D云引擎。 平台架构 平台特性 基于 …

C#,人工智能,机器人,路径规划,A*(AStar Algorithm)算法、源代码及计算数据可视化

Peter Hart Nils Nilsson Bertram Raphael 参考: C#,人工智能(AI)机器人路径规划(Path Planning)的ARA*(Anytime Replanning A* Algorithm)算法与源程序https://blog.csdn.net/…

Apache Doris (六十四): Flink Doris Connector - (1)-源码编译

🏡 个人主页:IT贫道-CSDN博客 🚩 私聊博主:私聊博主加WX好友,获取更多资料哦~ 🔔 博主个人B栈地址:豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 1. Flink与Doris版本兼容

【大数据】Flink 详解(八):SQL 篇 Ⅰ

《Flink 详解》系列(已完结),共包含以下 10 10 10 篇文章: 【大数据】Flink 详解(一):基础篇【大数据】Flink 详解(二):核心篇 Ⅰ【大数据】Flink 详解&…

基于Java+SSM+MYSQL的助农特色农产品销售系统详细设计和实现【附源码】

基于JavaSSM助农特色农产品销售系统详细设计和实现【附源码】 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各种定…

笔试面试题——继承和多态

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、什么是多态?二、什么是重载、重写(覆盖)、重定义(隐藏)?三、 inli…

使用 Python 创造你自己的计算机游戏(游戏编程快速上手)第四版:第十九章到第二十一章

十九、碰撞检测 原文:inventwithpython.com/invent4thed/chapter19.html 译者:飞龙 协议:CC BY-NC-SA 4.0 碰撞检测涉及确定屏幕上的两个物体何时相互接触(即发生碰撞)。碰撞检测对于游戏非常有用。例如,如…

《动手学深度学习》学习笔记 第9章 现代循环神经网络

本系列为《动手学深度学习》学习笔记 书籍链接:动手学深度学习 笔记是从第四章开始,前面三章为基础知识,有需要的可以自己去看看 关于本系列笔记: 书里为了让读者更好的理解,有大篇幅的描述性的文字,内容很…

成功 BOM 流程的五个基本要素

您应该以确保 BOM 流程的方式实现和启用它们: 准确的 当前的 完全的 清除 可行的 追求准确性 为下游提供准确数据 制造商使用其 BOM 来通知下游操作他们需要执行什么。不言而喻,向其他团队和员工提供准确的信息至关重要;否则&…

transbigdata笔记:栅格参数优化

在transbigdata中,栅格参数有如下几个 params(lonStart,latStart,deltaLon,deltaLat,theta) 如何选择合适的栅格参数是很重要的事情,这会对最终的分析结果产生很大的影响。 怎么选择参数,和数据以及分析的目的息息相关,transbi…

25考研英语复习计划

Hello各位小伙伴大家好,今天要给大家分享的是英语备考计划,大家可以作为参考,制定适合自己的备考计划。 【英一/二】 英语分为英一、英二,一般学硕英一,专硕英二。 英一要比英二难度大。 【复习计划】 1-2月&#xf…