0.9.2、线程池——核心线程数、阻塞队列、最大线程数之间的关系
文章目录
- 线程池内部运行过程
- 验证思路
- 确保先提交的任务优先被线程池处理
- 确保执行的任务占有足够久的线程池资源
- 可观测的阻塞队列大小
- 充分的信息
- 代码
- 自定义线程池
- 结果
- 结论
- 基本几结论
- 新任务提交在线程池内部处理的优先级
线程池内部运行过程
线程池的初始参数中包含 核心线程数、最大线程数、线程池线程空闲回收时间、阻塞队列、线程工厂、拒绝策略。
那么线程池是如何管理线程和阻塞队列的关系呢?
验证思路
确保先提交的任务优先被线程池处理
多线程执行本身是无序的,原因在于并发操作下,后面提交的任务也可能被先运行,因此,为了确保先提交的任务优先被线程池处理,我们使用延迟提交下一个任务的方法,确保已提交的任务优先获得线程池处理的机会(处理不等于执行)
确保执行的任务占有足够久的线程池资源
为了方便观察核心线程数、阻塞队列和最大线程数之间的关系,我们需要确保一个任务在执行的时候占用足够久的时间,以确保下一个任务到来之时,之前的任务还占用着线程池的资源,因而可以进入到阻塞队列或者新申请一个线程池的线程资源
可观测的阻塞队列大小
我们使用 ArrayBlockingQueue 指定阻塞队列大小,用以验证阻塞队列和最大线程数之间的关系
充分的信息
自定义一个线程池,然后先运行6个线程任务,然后等待所有任务执行完,然后再次提交6个线程任务,然后等待所有任务执行完,期间不断打印线程池的活跃线程数、线程阻塞队列大小、完成任务、线程池线程和执行任务之间的关系
代码
自定义线程池
import lombok.SneakyThrows;import java.util.concurrent.*;/*** @Title: 线程池运行原理* @Description:* @Author: bestcxx* @Version: v1.0* @Date:2021-12-05* @Updatedby:*/
public class ThreadPool {private final static ThreadPoolExecutor executor = getThreadPool();public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 31; i++) {printPoolInfo(executor);if (i < 6 || (i >= 15 && i <= 20)) {getThreadPool().execute(new MyThread("任务" + i));//getThreadPool().submit(new MyThread("任务" + i));}Thread.sleep(900);}//ArrayBlockingQueue;//LinkedBlockingQueue;//PriorityBlockingQueue;//DelayQueue;//SynchronousQueue;//LinkedBlockingDeque;//LinkedTransferQueue;
/**CAPACITY 00011111111111111111111111111111 536870911~CAPACITY 11100000000000000000000000000000 -536870912RUNNING 11100000000000000000000000000000 -536870912SHUTDOWN 00000000000000000000000000000000 0STOP 00100000000000000000000000000000 536870912TIDYING 01000000000000000000000000000000 1073741824TERMINATED 01100000000000000000000000000000 1610612736*/}public static class MyThread extends Thread {String threadName = 0 + "";public MyThread(String threadName) {this.threadName = threadName;}@SneakyThrows@Overridepublic void run() {super.run();System.out.println("线程资源:" + Thread.currentThread().getName() + " " + threadName);Thread.sleep(6000L);}}private static class ThreadPoolExecutorHolder {private static ThreadPoolExecutor instance = new ThreadPoolExecutor(2, 4, 0,TimeUnit.SECONDS, new ArrayBlockingQueue<>(2));}public static synchronized ThreadPoolExecutor getThreadPool() {return ThreadPoolExecutorHolder.instance;}public static void printPoolInfo(ThreadPoolExecutor executor) {System.out.println(String.format("设定核心线程数: %d," +"设定最大线程数: %d," +"活跃线程数: %d ," +"阻塞队列任务数: %d," +"总任务数: %d," +"已执行完任务数: %d",executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getActiveCount(),executor.getQueue().size(), executor.getTaskCount(), executor.getCompletedTaskCount()));}}
结果
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 0 ,阻塞队列任务数: 0,总任务数: 0,已执行完任务数: 0
线程资源:pool-1-thread-1 任务0
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 1 ,阻塞队列任务数: 0,总任务数: 1,已执行完任务数: 0
线程资源:pool-1-thread-2 任务1
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 0,总任务数: 2,已执行完任务数: 0
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 1,总任务数: 3,已执行完任务数: 0
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 2,总任务数: 4,已执行完任务数: 0
线程资源:pool-1-thread-3 任务4
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 3 ,阻塞队列任务数: 2,总任务数: 5,已执行完任务数: 0
线程资源:pool-1-thread-4 任务5
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 2,总任务数: 6,已执行完任务数: 0
线程资源:pool-1-thread-1 任务2
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 1,总任务数: 6,已执行完任务数: 1
线程资源:pool-1-thread-2 任务3
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 0,总任务数: 6,已执行完任务数: 2
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 0,总任务数: 6,已执行完任务数: 2
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 0,总任务数: 6,已执行完任务数: 2
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 3 ,阻塞队列任务数: 0,总任务数: 6,已执行完任务数: 3
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 0,总任务数: 6,已执行完任务数: 4
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 0,总任务数: 6,已执行完任务数: 4
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 1 ,阻塞队列任务数: 0,总任务数: 6,已执行完任务数: 5
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 0 ,阻塞队列任务数: 0,总任务数: 6,已执行完任务数: 6
线程资源:pool-1-thread-1 任务15
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 1 ,阻塞队列任务数: 0,总任务数: 7,已执行完任务数: 6
线程资源:pool-1-thread-2 任务16
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 0,总任务数: 8,已执行完任务数: 6
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 1,总任务数: 9,已执行完任务数: 6
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 2,总任务数: 10,已执行完任务数: 6
线程资源:pool-1-thread-5 任务19
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 3 ,阻塞队列任务数: 2,总任务数: 11,已执行完任务数: 6
线程资源:pool-1-thread-6 任务20
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 2,总任务数: 12,已执行完任务数: 6
线程资源:pool-1-thread-1 任务17
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 1,总任务数: 12,已执行完任务数: 7
线程资源:pool-1-thread-2 任务18
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 0,总任务数: 12,已执行完任务数: 8
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 0,总任务数: 12,已执行完任务数: 8
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 4 ,阻塞队列任务数: 0,总任务数: 12,已执行完任务数: 8
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 3 ,阻塞队列任务数: 0,总任务数: 12,已执行完任务数: 9
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 0,总任务数: 12,已执行完任务数: 10
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 2 ,阻塞队列任务数: 0,总任务数: 12,已执行完任务数: 10
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 1 ,阻塞队列任务数: 0,总任务数: 12,已执行完任务数: 11
设定核心线程数: 2,设定最大线程数: 4,活跃线程数: 0 ,阻塞队列任务数: 0,总任务数: 12,已执行完任务数: 12
结论
基本几结论
- 线程池初始化的活跃线程数为0
- 当活跃线程数<核心线程数,且活跃线程在执行任务,线程池会新生成线程用以执行提交的任务
- 当活跃线程数=核心线程数,且活跃线程在执行任务,新任务会优先被放置到阻塞队列
- 当活跃线程数=核心线程数,且活跃线程在执行任务,且阻塞队列已满,且没有活跃线程数<最大线程数,则线程池会新生成一个线程来执行任务
- 当线程空闲,会被逐步回收,如果持续没有新任务提交,线程池活跃线程数会降低为0
新任务提交在线程池内部处理的优先级
核心线程 > 阻塞队列 > 扩容的线程
0.9.2、线程池——核心线程数、阻塞队列、最大线程数之间的关系相关推荐
- 【重难点】【JUC 05】线程池核心设计与实现、线程池使用了什么设计模式、要你设计的话,如何实现一个线程池
[重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计的话,如何实现一个线程池 文章目录 [重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计 ...
- Java多线程闲聊(四):阻塞队列与线程池原理
Java多线程闲聊(四)-阻塞队列与线程池原理 前言 复用永远是人们永恒的主题,这能让我们更好地避免重复制造轮子. 说到多线程,果然还是绕不开线程池,那就来聊聊吧. 人们往往相信,世界是存在一些规律的 ...
- 线程池核心数与最大线程数设置
线程池核心数与最大线程数设置 总结: 核心线程 CPU密集型:核心线程数=CPU核心数(或 核心线程数=CPU核心数+1) I/O密集型:核心线程数=2*CPU核心数(或 核心线程数=CPU核心数/( ...
- 线程池——核心线程数设置依据
根据线程数设置依据 最大线程数:原则上就是性能最高线程数,因为此时性能已经是最高,再设置比他大的线程数反而性能变低.极端情况下才会使用到最大线程数,正常情况下不应频繁出现超过核心线程数的创建. 核心线 ...
- Java线程池核心线程数与最大线程数的区别
线程池策略 corePoolSize:核心线程数:maximunPoolSize:最大线程数 每当有新的任务到线程池时, 第一步: 先判断线程池中当前线程数量是否达到了corePoolSize,若未达 ...
- Java_Java多线程_Java线程池核心参数 与 手动创建线程池
参考文章: 1.浅谈线程池ThreadPoolExecutor核心参数 https://www.cnblogs.com/stupid-chan/p/9991307.html 2.Java线程池 Thr ...
- ThreadPoolExecutor线程池核心参数详解
理解ThreadPoolExecutor线程池的corePoolSize.maximumPoolSize和poolSize 我们知道,受限于硬件.内存和性能,我们不可能无限制的创建任意数量的线程,因为 ...
- 【Android 异步操作】线程池 ( Worker 简介 | 线程池中的工作流程 runWorker | 从线程池任务队列中获取任务 getTask )
文章目录 一.线程池中的 Worker ( 工作者 ) 二.线程池中的工作流程 runWorker 三.线程池任务队列中获取任务 getTask 在博客 [Android 异步操作]线程池 ( 线程池 ...
- 多线程—线程池Executor框架及四种常用线程池
池化技术应用:线程池.数据库连接池.http连接池等等. 池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率. 使用线程池的好处: 降低资源消耗:通过重复利用已创建的线程降低线程创建和 ...
最新文章
- avs php,【求助!】小白求个标准反交错AVS脚本和解答困扰我的几个问题!!
- tomcat 之APR优化
- python函数式编程思想_以python为例,浅谈函数式编程思想
- Sklearn中的CV与KFold详解
- .h头文件 .lib库文件 .dll动态库文件之间的关系
- 信息学奥赛一本通(1121:计算矩阵边缘元素之和)
- Gulp新手入门教程
- Oracle中日期和时间字段的日常使用
- mtk android工具包,MTK Android software Tools工具的说明
- mysql 5.6.19 linux_MySQL 5.6.19升级到 5.7.9 步骤记录
- django文件——django + jquery-file-upload上传篇(二)-- 插件实现文件上传+进度条显示 +拖入文件上传...
- python导入selenium快捷键_python,_Selenium工具自动打开的浏览器和用快捷方式打开的样式不一样?,python - phpStudy...
- 语言题库安装包312mb_大学为什么要考取计算机二级,以后很需要,附二级Msoffice题库...
- 如何监听事件里发生的错误_Swing 如何进行事件监听
- hping 详解_hping3 使用详解
- 虚拟打印机安装后没了该怎么办
- C语言实现EPSG:4326和EPSG:3857的互转
- 信息奥赛课课通(C++)p139-例3幸运数的划分
- android系统自带分享图片到微信,通过intent和无障碍服务实现分享图片+文字到微信朋友圈...
- 《红色警戒3》简体中文完美整合版下载
热门文章
- 关于Adobe Photoshop 2021另存为图片找不到JPEG、PNG等格式的解决办法
- python-cookie http.cookiejar用法
- mysql tab键替换为空_记事本中TAB键替换为空格键的方法
- 给XLua生成Unity Api的EmmyLua代码提示
- 国家出手管人工智能AI了
- 上大学学计算机会学一些什么东西吗,“上大学一年,你到底学到了些什么?”...
- 开发工具-Docker学习
- Unity人工智能机器学习(环境安装篇)
- 第十章 实验一 分析成绩单
- Java如何往前端传输echarts数据