网上关于线程池的八股文太多了我不多说,说了你也记不住,记住了也理解不了,理解了也不会用…

想了很久,终于想出一个demo,加上十个场景,让你能逐步理解线程池真正的工作流程

相信我,认真看完这篇文章,你能彻底掌握一个Java核心知识点,不亏


线程池无非就那几个参数:核心线程、最大线程、回收时间、队列,没啥难的,有手就能学废

我这里直接上demo,不知道参数啥意思的可以先去隔壁补补课,虽然本文也会提到,但你最好先大概知道点,线程池实现运行机制总结

上才艺

public class ThreadPoolExecutorTest {private static int taskCount = 50;//任务数private static AtomicInteger taskCountExecuted;//实际完成任务数public static void main(String[] args) {taskCountExecuted = new AtomicInteger();ThreadPoolExecutor executor = new ThreadPoolExecutor(10,//核心线程数20,//最大线程数5,//非核心回收超时时间TimeUnit.SECONDS,//超时时间单位new ArrayBlockingQueue<>(30)//任务队列);System.out.println("总任务数:" + taskCount);long start = System.currentTimeMillis();//模拟任务提交for (int i = 0; i < taskCount; i++) {Thread thread = new Thread(() -> {try {Thread.sleep(500);//模拟执行耗时System.out.println("已执行" + taskCountExecuted.addAndGet(1) + "个任务");} catch (InterruptedException e) {e.printStackTrace();}});try {//注意这里我try起来了,默认拒绝策略会报错executor.execute(thread);} catch (RejectedExecutionException e) {taskCount = executor.getActiveCount() + executor.getQueue().size();}}long end = 0;while (executor.getCompletedTaskCount() < taskCount) {end = System.currentTimeMillis();}System.out.println(taskCountExecuted + "个任务已执行,总耗时:" + (end - start));executor.shutdown();}
}

重点来了,我们带着问题来看demo

如上,new了个线程池,core线程数10,最大线程数20,任务队列容量30,请听题!!

问题0:往上述线程池中提交5个任务,任务执行完总耗时多少?

分析:我核心线程数10,也就是说10个线程会长期处于活跃状态,来任务立马能执行,5<10,所以5个任务立马全部执行,多线程并行当然是异步,所以是500ms

插个嘴:为什么不是500而是540,因为代码执行需要花时间,毕竟是模拟提交任务,并不是真正一瞬间提交完,而且误差跟你电脑cpu频率有关

问题1:提交10个任务,总耗时多少?

依然是500,10个任务和5个任务其实都一样,没超过核心线程数,来一个执行一个

问题2:提交11个任务,总耗时多少?

1000,别惊讶,这就是很多人没搞懂线程池机制的关键点,虽然只多了一个任务,但是第11个任务不会马上执行,因为队列没满,所以前10个任务会立马执行,而第11个会被扔到队列中,等有线程空出来了再执行

问题3:提交20个任务,总耗时多少?

也是1000,别问为什么也别杠,今天就是耶稣来了它也是1000,这20个任务,前10个任务来一个执行一个,从第11个到第20个会全部丢进队列,当前十个任务有任务执行完了,才会从队列取出执行

问题4:提交30个任务,总耗时多少?

当然是1500啦,30/10=3,3*500=1500

问题5:提交40个任务,总耗时多少?

当然是2000啦,10+10+10+10,我不想解释

重点来了!!
重点来了!!
重点来了!!

问题6:提交41个任务,总耗时多少?

也是2000,很多人会认为是1500,11+11+11+8,其实不然,这里先记下,我后面说,先继续往下看

问题7:提交45个任务,总耗时多少?

1500,没错就是1500,15+15+15

问题8:提交50个任务,总耗时多少?

1500,20+20+10

问题9:提交51个任务,总耗时多少?
也是1500,这个线程池同时最大接收50个任务,因为我没设置拒绝策略,默认是AbortPolicy,即超出的任务会被丢弃并抛出RejectedExecutionException异常,demo中没报错是因为我try了

最后来说刚才的遗留问题,为啥41个任务2000,45个任务就1500??

其实很多人没把这个搞懂的,后面几个问题我都写了个一串加号(这个搞懂,线程池你就算掌握了)

如40个任务时,10+10+10+10,这代表所有任务分4组完成,每组执行10个,因为多线程是异步,所以每组执行时间就等于单个任务执行时间,即500ms,所以40个任务就是500+500+500+500=2000

而41个任务时,是11+11+11+8,所以40个任务也是500+500+500+500=2000(肯定会有小伙伴问,41个任务已经超出了队列容量,线程池中线程为啥没达到最大线程数,应该是20+20+1才对啊)

记住一句话
任务数 <= 核心线程数时,线程池中工作线程数 = 任务数
核心线程数 + 队列容量 < 任务数 <= 最大线程数 + 队列容量时,工作线程数 = 任务数 - 队列容量

所以

再来继续看

41个任务时,41-30=11,执行批次为11+11+11+8,即500+500+500+500=2000,有问题吗?没有问题

45个任务时,45-30=15,所以15+15+15,即500+500+500=1500,有问题吗?没有问题

50个任务时,50-30=20,20+20+10,即500+500+500=1500,有问题吗?依然没有问题


课后留个问题,44个任务耗时多少?

希望你自己去跑一下,别不识抬举


文末补充个冷知识,核心线程数也可以被回收,ThreadPoolExecutor有个属性叫 allowCoreThreadTimeOut

ThreadPoolExecutor给我们提供了一个public方法allowCoreThreadTimeOut,通过**allowCoreThreadTimeOut( true )**就能设置


博客是今天写的

demo是昨天想的

头发是前天想demo时掉的

这是我好几根头发换来的demo,老板见了都要激动的拍打轮椅,家里有条件的都把demo复制下来跑一跑,没条件的朗诵并背诵全文

完结
撒花


ok我话说完

一个demo让你彻底理解线程池工作流程相关推荐

  1. 一个DEMO让你彻底理解线程池

    目录 一.简介 二.线程池任务场景 场景一:提交5个任务,执行总耗时500ms 场景二:提交10个任务,执行总耗时500ms 场景三:提交11个任务,执行总耗时1000ms 场景四:提交20个任务,执 ...

  2. 自定义线程池-线程池工作流程介绍

    ThreadPoolExecutor参数详解 我们可以通过下面的场景理解ThreadPoolExecutor中的各个参数; a客户(任务)去银行(线程池)办理业务,但银行刚开始营业,窗口服务员还未就位 ...

  3. Java核心(二)深入理解线程池ThreadPool

    本文你将获得以下信息: 线程池源码解读 线程池执行流程分析 带返回值的线程池实现 延迟线程池实现 为了方便读者理解,本文会由浅入深,先从线程池的使用开始再延伸到源码解读和源码分析等高级内容,读者可根据 ...

  4. Java提高班(二)深入理解线程池ThreadPool

    本文你将获得以下信息: 线程池源码解读 线程池执行流程分析 带返回值的线程池实现 延迟线程池实现 为了方便读者理解,本文会由浅入深,先从线程池的使用开始再延伸到源码解读和源码分析等高级内容,读者可根据 ...

  5. 通过ThreadPoolExecutor与ForkJoinPool比较,分别对比其execute ,submit 等方法提交线程池任务的区别,来深入理解线程池及并发编程

    前言 以前使用线程池,对execute . submit 等方法提交线程池任务的区别比较模糊,现在通过ThreadPoolExecutor与ForkJoinPool比较,分别对比其execute ,s ...

  6. 深入理解线程池 ThreadPoolExecutor

    前言 网上关于线程池详解的文章很多,陆续也看了不少,从刚开始的怎么使用到原理解析,但是一直想自己写一篇,记录一下自己的学习历程,之前看源码一直是一知半解,不得要领,最近静下心来仔细看,发现以前看不懂的 ...

  7. 深入理解线程池(ThreadPoolExecutor)——细致入微的讲源码。

    在上一篇博文<图解线程池原理>中,大体上介绍了线程池的工作原理. 这一篇从源码层面,细致剖析,文章会很长. 如果上篇文章内容没吸收,先看上篇,先易后难嘛. 本文源码是 java 1.8 版 ...

  8. java如何创建一个两个数的队列_java线程池 如何构建一个线程立即到拉到MAX数量跑业务,线程到MAX了,额外的队列可以存储任务的线程池...

    背景:JDK的线程池的运作原理 : JDK的线程池的构造函数有7个参数,分别是corePoolSize.maximumPoolSize.keepAliveTime.unit.workQueue.thr ...

  9. 线程池工作原理和实现原理

    为什么要使用线程池 平时讨论多线程处理,大佬们必定会说使用线程池,那为什么要使用线程池?其实,这个问题可以反过来思考一下,不使用线程池会怎么样?当需要多线程并发执行任务时,只能不断的通过new Thr ...

最新文章

  1. 浅谈本地文件包含利用
  2. String和C#中的string有什么区别?
  3. 软件测试 图覆盖,软件测试(四)——图覆盖
  4. Windows异常学习笔记(四)—— 编译器扩展SEH
  5. python3 for计数_python怎么实现计数?
  6. Linux下redis的安装及用法
  7. 搭建svn,创建svn项目
  8. 《几何与代数导引》习题1.34.2
  9. 建立 CLR Stored Procedure/Function 的小範例
  10. linux格式u盘没有fat32,U盘,移动硬盘安装Linux的主分区,逻辑分区,FAT32格式分区的问题...
  11. 3位格雷码的顺序编码_格雷码编码规则_格雷码有什么规律
  12. 如何在 vuePress中添加博客导流公众号-即输入验证码解锁全站文章
  13. Linux内核之——等待队列wait queue
  14. Python学习笔记——函数式方程
  15. 【机器学习】西瓜书一些关键词
  16. TIA博途中如何通过Prodiag功能制作报警并显示在HMI上?
  17. 使用正则表达式提取文件中满足条件的内容
  18. 在使用计算机时可以用什么键关机,电脑死机按什么键关机重启
  19. 零撸项目-Star Network注册流程
  20. 听罗辑思维关于商业模式的思考

热门文章

  1. 世界五大学习方法之西蒙学习法
  2. unity3d 5.6烘焙教程 持续更新中
  3. 【MATLAB图像处理实用案例详解】目录
  4. 按键精灵 大沙漠插件注册
  5. EN 16034: 防火门CE认证
  6. python对接萤石摄像头,不买SD卡,将萤石摄像头实时视频、抓拍图片保存到PC本地
  7. [Neepuctf2021]wp
  8. R语言p值校正函数p.adjust
  9. 简单、稳定、可控:老牌财经网站上云记!
  10. [C] 二、回调函数