文章目录

  • 线程池内部运行过程
  • 验证思路
    • 确保先提交的任务优先被线程池处理
    • 确保执行的任务占有足够久的线程池资源
    • 可观测的阻塞队列大小
    • 充分的信息
  • 代码
    • 自定义线程池
    • 结果
  • 结论
    • 基本几结论
    • 新任务提交在线程池内部处理的优先级

线程池内部运行过程

线程池的初始参数中包含 核心线程数、最大线程数、线程池线程空闲回收时间、阻塞队列、线程工厂、拒绝策略。
那么线程池是如何管理线程和阻塞队列的关系呢?

验证思路

确保先提交的任务优先被线程池处理

多线程执行本身是无序的,原因在于并发操作下,后面提交的任务也可能被先运行,因此,为了确保先提交的任务优先被线程池处理,我们使用延迟提交下一个任务的方法,确保已提交的任务优先获得线程池处理的机会(处理不等于执行)

确保执行的任务占有足够久的线程池资源

为了方便观察核心线程数、阻塞队列和最大线程数之间的关系,我们需要确保一个任务在执行的时候占用足够久的时间,以确保下一个任务到来之时,之前的任务还占用着线程池的资源,因而可以进入到阻塞队列或者新申请一个线程池的线程资源

可观测的阻塞队列大小

我们使用 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、线程池——核心线程数、阻塞队列、最大线程数之间的关系相关推荐

  1. 【重难点】【JUC 05】线程池核心设计与实现、线程池使用了什么设计模式、要你设计的话,如何实现一个线程池

    [重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计的话,如何实现一个线程池 文章目录 [重难点][JUC 05]线程池核心设计与实现.线程池使用了什么设计模式.要你设计 ...

  2. Java多线程闲聊(四):阻塞队列与线程池原理

    Java多线程闲聊(四)-阻塞队列与线程池原理 前言 复用永远是人们永恒的主题,这能让我们更好地避免重复制造轮子. 说到多线程,果然还是绕不开线程池,那就来聊聊吧. 人们往往相信,世界是存在一些规律的 ...

  3. 线程池核心数与最大线程数设置

    线程池核心数与最大线程数设置 总结: 核心线程 CPU密集型:核心线程数=CPU核心数(或 核心线程数=CPU核心数+1) I/O密集型:核心线程数=2*CPU核心数(或 核心线程数=CPU核心数/( ...

  4. 线程池——核心线程数设置依据

    根据线程数设置依据 最大线程数:原则上就是性能最高线程数,因为此时性能已经是最高,再设置比他大的线程数反而性能变低.极端情况下才会使用到最大线程数,正常情况下不应频繁出现超过核心线程数的创建. 核心线 ...

  5. Java线程池核心线程数与最大线程数的区别

    线程池策略 corePoolSize:核心线程数:maximunPoolSize:最大线程数 每当有新的任务到线程池时, 第一步: 先判断线程池中当前线程数量是否达到了corePoolSize,若未达 ...

  6. Java_Java多线程_Java线程池核心参数 与 手动创建线程池

    参考文章: 1.浅谈线程池ThreadPoolExecutor核心参数 https://www.cnblogs.com/stupid-chan/p/9991307.html 2.Java线程池 Thr ...

  7. ThreadPoolExecutor线程池核心参数详解

    理解ThreadPoolExecutor线程池的corePoolSize.maximumPoolSize和poolSize 我们知道,受限于硬件.内存和性能,我们不可能无限制的创建任意数量的线程,因为 ...

  8. 【Android 异步操作】线程池 ( Worker 简介 | 线程池中的工作流程 runWorker | 从线程池任务队列中获取任务 getTask )

    文章目录 一.线程池中的 Worker ( 工作者 ) 二.线程池中的工作流程 runWorker 三.线程池任务队列中获取任务 getTask 在博客 [Android 异步操作]线程池 ( 线程池 ...

  9. 多线程—线程池Executor框架及四种常用线程池

    池化技术应用:线程池.数据库连接池.http连接池等等. 池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率. 使用线程池的好处: 降低资源消耗:通过重复利用已创建的线程降低线程创建和 ...

最新文章

  1. avs php,【求助!】小白求个标准反交错AVS脚本和解答困扰我的几个问题!!
  2. tomcat 之APR优化
  3. python函数式编程思想_以python为例,浅谈函数式编程思想
  4. Sklearn中的CV与KFold详解
  5. .h头文件 .lib库文件 .dll动态库文件之间的关系
  6. 信息学奥赛一本通(1121:计算矩阵边缘元素之和)
  7. Gulp新手入门教程
  8. Oracle中日期和时间字段的日常使用
  9. mtk android工具包,MTK Android software Tools工具的说明
  10. mysql 5.6.19 linux_MySQL 5.6.19升级到 5.7.9 步骤记录
  11. django文件——django + jquery-file-upload上传篇(二)-- 插件实现文件上传+进度条显示 +拖入文件上传...
  12. python导入selenium快捷键_python,_Selenium工具自动打开的浏览器和用快捷方式打开的样式不一样?,python - phpStudy...
  13. 语言题库安装包312mb_大学为什么要考取计算机二级,以后很需要,附二级Msoffice题库...
  14. 如何监听事件里发生的错误_Swing 如何进行事件监听
  15. hping 详解_hping3 使用详解
  16. 虚拟打印机安装后没了该怎么办
  17. C语言实现EPSG:4326和EPSG:3857的互转
  18. 信息奥赛课课通(C++)p139-例3幸运数的划分
  19. android系统自带分享图片到微信,通过intent和无障碍服务实现分享图片+文字到微信朋友圈...
  20. 《红色警戒3》简体中文完美整合版下载

热门文章

  1. 关于Adobe Photoshop 2021另存为图片找不到JPEG、PNG等格式的解决办法
  2. python-cookie http.cookiejar用法
  3. mysql tab键替换为空_记事本中TAB键替换为空格键的方法
  4. 给XLua生成Unity Api的EmmyLua代码提示
  5. 国家出手管人工智能AI了
  6. 上大学学计算机会学一些什么东西吗,“上大学一年,你到底学到了些什么?”...
  7. 开发工具-Docker学习
  8. Unity人工智能机器学习(环境安装篇)
  9. 第十章 实验一 分析成绩单
  10. Java如何往前端传输echarts数据