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

2024-01-18 02:44

本文主要是介绍【昕宝爸爸小模块】图文源码详解什么是线程池、线程池的底层到底是如何实现的,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

➡️博客首页       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 (资源池)


在这里插入图片描述

这篇关于【昕宝爸爸小模块】图文源码详解什么是线程池、线程池的底层到底是如何实现的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/617900

相关文章

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、