首页 > 其他分享 >2023年7月7日,线程池的调用原理,线程池底层,任务队列

2023年7月7日,线程池的调用原理,线程池底层,任务队列

时间:2023-07-07 23:31:50浏览次数:36  
标签:队列 maximumPoolSize -- 任务 线程 2023 执行

线程池的调用原理

线程池的七大参数:

核心线程数、最大线程数、任务队列、拒绝策略、闲置时间、时间单位、线程工厂

任务进入线程池后线程池的执行顺序:

  1. 核心线程(用完)---处理完一个任务后会取出任务队列中的第一个任务来执行
  2. 任务队列(装满)
  3. 普通线程(用完)
  4. 拒绝策略

2023年7月7日,线程池的调用原理,线程池底层,任务队列_闲置时间

深入线程池

ExecutorService pool = Executors.newSingleThreadExecutor();

ExecutorService pool = Executors.newFixedThreadPool(3);

ExecutorService pool = Executors.newCachedThreadPool();

三种线程池底层都是ThreadPoolExecutor类的对象

-- 分析ThreadPoolExecutor类的构造方法源码--------------------------------
public ThreadPoolExecutor(
	int corePoolSize,		------------- 核心线程数量 
    int maximumPoolSize,	------------- 最大线程数量 
	long keepAliveTime,		------------- 闲置时间,作用于核心线程数与最大线程数之间的线程
	TimeUnit unit,			------------- keepAliveTime的时间单位(可以是毫秒、秒....)
	BlockingQueue<Runnable> workQueue, -- 任务队列
	ThreadFactory threadFactory, -------- 线程工厂
	RejectedExecutionHandler handler ---- 达到了线程界限和队列容量时的处理方案(拒绝策略)
) {}
执行步骤:
	1.创建线程池后
    2.任务提交后,查看是否有核心线程:
        3.1 没有 -> 就创建核心线程 -> 执行任务 -> 执行完毕后又回到线程池中
        3.2 有 -> 查看是否有闲置核心线程:
        	4.1 有 -> 执行任务 -> 执行完毕后又回到线程池
        	4.2 没有 -> 查看当前核心线程数是否核心线程数量:
        		5.1 否 -> 就创建核心线程 -> 执行任务 -> 执行完毕后又回到线程池中
        		5.2 是 -> 查看任务列表是否装载满:
        			6.1 没有 -> 就放入列表中,等待出现闲置线程
        			6.2 装满 -> 查看是否有普通线程(核心线程数到最大线程数量之间的线程)
        				7.1 没有 -> 就创建普通线程 -> 执行任务 -> 执行完毕后又回到线程池中
        				7.2 有 -> 查看是否有闲置普通线程
        					7.1.1 有 -> 执行任务 -> 执行完毕后又回到线程池中
        					7.1.2 没有 -> 查看现在所有线程数量是否为最大线程数:
        						8.1 是 -> 执行处理方案(默认处理抛出异常)
        						8.2 否 ->就创建普通线程-> 执行任务 -> 执行完毕后又回到线程池中     			
注:
	1.为了更好的理解,在这里区分核心线程和普通线程,实际上区分的这么清楚,都是线程
    2.默认的处理方案就是抛出RejectedExecutionException
总结:核心线程满载 -> 任务队列 -> 普通线程

-- 分析单个线程的线程池的源码 --------------------------------
ExecutorService pool = Executors.newSingleThreadExecutor();
new ThreadPoolExecutor(
    1, -- 核心线程数量 
    1, -- 最大线程数量 
    0L, -- 闲置时间
    TimeUnit.MILLISECONDS, -- 时间单位(毫秒)
    new LinkedBlockingQueue<Runnable>() -- 无界任务队列,可以无限添加任务
)  
-- 分析指定线程的线程池的源码 --------------------------------
ExecutorService pool = Executors.newFixedThreadPool(3);
new ThreadPoolExecutor(
    nThreads, -- 核心线程数量 
    nThreads, -- 最大线程数量 
    0L, -- 闲置时间
    TimeUnit.MILLISECONDS, -- 时间单位(毫秒)
    new LinkedBlockingQueue<Runnable>()-- 无界任务队列,可以无限添加任务
)
-- 创建可缓存线程的线程池 -----------------------------------
new ThreadPoolExecutor(
    0, -- 核心线程数量 
    Integer.MAX_VALUE,-- 最大线程数量 
    60L, -- 闲置时间
    TimeUnit.SECONDS, -- 时间单位(秒)
    new SynchronousQueue<Runnable>() -- 直接提交队列(同步队列):没有容量队列
    //线程数目不可控

Java自带的线程池底层使用用无界队列,都存在内存溢出的风险

任务队列

队列名称

详解

LinkedBlockingQueue无界任务队列

使用无界任务队列,线程池的任务队列可以无限制的添加新的任务,而线程池创建的最大线程数量就是你corePoolSize设置的数量,也就是说在这种情况下maximumPoolSize这个参数是无效的,哪怕你的任务队列中缓存了很多未执行的任务,当线程池的线程数达到corePoolSize后,就不会再增加了;若后续有新的任务加入,则直接进入队列等待,当使用这种任务队列模式时,一定要注意你任务提交与处理之间的协调与控制,不然会出现队列中的任务由于无法及时处理导致一直增长,直到最后资源耗尽的问题

SynchronousQueue 同步任务队列 直接提交任务队列

使用直接提交任务队列,队列没有容量,每执行一个插入操作就会阻塞,需要再执行一个删除操作才会被唤醒,反之每一个删除操作也都要等待对应的插入操作。 任务队列为SynchronousQueue,创建的线程数大于maximumPoolSize时,直接执行了拒绝策略抛出异常。 使用SynchronousQueue队列,提交的任务不会被保存,总是会马上提交执行。如果用于执行任务的线程数量小于maximumPoolSize,则尝试创建新的线程,如果达到maximumPoolSize设置的最大值,则根据你设置的handler执行拒绝策略。因此这种方式你提交的任务不会被缓存起来,而是会被马上执行,在这种情况下,你需要对你程序的并发量有个准确的评估,才能设置合适的maximumPoolSize数量,否则很容易就会执行拒绝策略;

ArrayBlockingQueue有界任务队列

使用有界任务队列,若有新的任务需要执行时,线程池会创建新的线程,直到创建的线程数量达到corePoolSize时,则会将新的任务加入到等待队列中。若等待队列已满,即超过ArrayBlockingQueue初始化的容量,则继续创建线程,直到线程数量达到maximumPoolSize设置的最大线程数量,若大于maximumPoolSize,则执行拒绝策略。在这种情况下,线程数量的上限与有界任务队列的状态有直接关系,如果有界队列初始容量较大或者没有达到超负荷的状态,线程数将一直维持在corePoolSize以下,反之当任务队列已满时,则会以maximumPoolSize为最大线程数上限。

PriorityBlockingQueue优先任务队列

使用优先任务队列,它其实是一个特殊的无界队列,它其中无论添加了多少个任务,线程池创建的线程数也不会超过corePoolSize的数量,只不过其他队列一般是按照先进先出的规则处理任务,而PriorityBlockingQueue队列可以自定义规则根据任务的优先级顺序先后执行。

标签:队列,maximumPoolSize,--,任务,线程,2023,执行
From: https://blog.51cto.com/u_15098423/6657619

相关文章

  • 消息队列-八股文
    消息队列选型-√kafka:优点:吞吐量高,性能高缺点:功能单一,有丢失消息的风险rocketMQ:优点:功能完善,性能好缺点:客户端仅支持JavaRocketMQ事务消息实现-※RocketMQ底层实现原理-※消息队列如何保证可靠传输可靠传输:不能多不能少1.消费者实现幂等性,哪怕多收消息,......
  • 2023-07-07:给出两个字符串 str1 和 str2。 返回同时以 str1 和 str2 作为子序列的最短
    2023-07-07:给出两个字符串str1和str2。返回同时以str1和str2作为子序列的最短字符串。如果答案不止一个,则可以返回满足条件的任意一个答案。输入:str1="abac",str2="cab"。输出:"cabac"。答案2023-07-07:大体步骤如下:1.初始化字符串str1和str2分别为"abac"......
  • 2023-07-07:给出两个字符串 str1 和 str2。 返回同时以 str1 和 str2 作为子序列的最短
    2023-07-07:给出两个字符串str1和str2。返回同时以str1和str2作为子序列的最短字符串。如果答案不止一个,则可以返回满足条件的任意一个答案。输入:str1="abac",str2="cab"。输出:"cabac"。答案2023-07-07:大体步骤如下:1.初始化字符串str1和str2分别为"abac"和"cab"......
  • 2023.7.7
    学习了java种的集合的基础部分,学习了java字符串的两道习题讲解,写了pta上的L1-009N个数求和,阅读了《大道至简》锻炼:哑铃和腹部训练问题:这个ptaL1-009N个数求和,其中写了一个函数longlonggcd(longlonga,longlongb){if(a%b==0)returnb;elseretur......
  • 2023.7.7 集训总结
    2023.7.7集训总结期末考试已经结束,文化课的同学们也已经放假,竞赛也停课集训了一段时间。现对这段时间的集训进行总结。CFCF的两场Div1或多或少地体现了我的缺陷:深入思考太慢,分析太久,在OI赛制可能还足够,但是在只有两个小时的CF赛制中却出现了问题,简单的T1要50分钟才能AC,导致T2......
  • 进程与线程的一个简单解释
    进程(process)和线程(thread)是操作系统的基本概念,但是它们比较抽象,不容易掌握。最近,我读到一篇材料,发现有一个很好的类比,可以把它们解释地清晰易懂。1.计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。2.假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一......
  • 2023全新FL Studio 21中文版水果编曲制作软件下载安装教程
    音乐在人们心中的地位日益增高,近几年音乐选秀的节目更是层出不穷,喜爱音乐,创作音乐的朋友们也是越来越多,音乐的类型有很多,好比古典,流行,摇滚等等。对新手友好程度基本上在首位,电音类制作支持仅次于AbletonPush,调用音色和素材很方便。因此初学阶段以及对电音需求高、依赖素材偏多的制......
  • imazing是什么软件?2023年最新imazing2.17.6官网下载
    imazing是什么软件?iMazing是一款iOS设备管理软件,iPhone、iPad、iPod都可以使用。用iMazing可以对iOS系统设备进行数据传输与备份,可以管理相册照片、短信、通讯录、音乐、铃声等等,在Windows/Mac电脑中传输、备份也非常方便。为什么选择iMazingiMazing功能强大、易于使用,可以帮助您......
  • 进程池和线程池
    一、进程池1、进程池 ProcessPoolExecutor优点:减少进程创建和销毁的开销:创建和销毁进程是一个相对耗时的操作,涉及到操作系统的系统调用和资源分配。使用进程池,可以预先创建一组进程,并在需要时重用这些进程,避免了频繁的进程创建和销毁开销,提高了程序的性能和效率。控制并......
  • 20230706巴蜀暑期集训测试总结
    T1我是个大聪明!一眼矩乘。构造转移矩阵构造了3.5h!最开始以为只有\(15\times15\),直接手打。写到一半发现不一定四种颜色都有,是\(52\times52\)的,这时候狗被脑子吃了,还想手打,于是就打到了3h。差不多打了一大半,脑子终于把狗还回来了,意识到就算打完也不可能调得出来,就开始另辟蹊径,......