JDK1.8中的线程池

上面这段代码一直在用,面试的时候也经常被问到,却从未深究过,不知道线程池到底是怎么回事,今天看看源代码,一探其究竟

线程池主要控制的状态是ctl,它是一个原子的整数,其包含两个概念字段:
- workerCount:有效的线程数量
- runState:线程池的状态
为了在一个整型值里面包含这两个字段,我们限制workerCount最多2的29次方减1
runState的值有这样几种:
- RUNNING: 接受新的任务,并处理队列中的任务
- SHUTDOWN:不接受新的任务,继续处理队列中的任务
- STOP: 不接受新的任务,也不处理队列中的任务,并且中断正在处理的任务
- TIDYING: 所有任务都结束了,workerCount是0,通过调用terminated()方法转换状态
- TERMINATED:terminated()方法已经完成
状态之间的转换时这样的:
RUNNING -> SHUTDOWN
调用shutdown()方法,或者隐式的调用finalize()方法
(RUNNING or SHUTDOWN) -> STOP
调用shoutdownNow()方法
SHUTDOWN -> TIDYING
当队列和池都是空的时候
STOP -> TIDYING
当池是空的时候
TIDYING -> TERMINATED
当terminated()方法调用完成时
Integer.SIZE=31
Integer.SIZE - 3 = 29
所以,COUNT_BITS = 29
高3位存储runState
接下来看最复杂的那个构造方法
参数详解
- corePoolSize:保持在池中的线程数(PS:即使它们处于空闲状态)
- maximumPoolSize:池中允许的最大线程数
- keepAliveTime:当线程数超过核心线程数的时候,超出的线程的最大生存时间
- unit:keepAliveTime的单位
- workQueue:维护待处理的任务的队列
- threadFactory:创建线程的工厂
1、如果正在运行的线程数少于核心线程数,则新建一个线程去运行这个任务
2、如果工作队列没有满,则放到工作队列中
3、如果工作队列已满(PS:workQueue.offer(command)返回false),则再新建线程
4、若线程数已经达到最大线程数则reject(command)
在前面execute方法中,有3处调用了addWork()方法
第一处,如果当前有效线程数少于核心线程数,则调用之,此时线程数的边界是核心线程数
第二处,如果当前有效线程数超过核心线程数,并且将新任务放到队列中,此时有效线程数是0,则创建一个新线程
第三处,如果当前有效线程数超过核心线程数,并且队列已经放满了,并且有效线程数小于最大线程数,此时调用以创建新线程,
当前的有效线程都在works里面,而works里面放的是Worker对象,接下来看Worker
前一步中,线程的start()方法,线程运行的时候执行run()方法,而Worker继承Runnable并重新run()方法,run()方法又调用外部的runWorker()方法,所以,在线程池中新创建的线程运行时调用的是runWorker()方法
runWorker()方法循环的从队列中取出任务并执行它。也就是说,池中所有的线程都是在创建的时候如果传进来新任务,则先执行新任务,然后循环从队列中取出任务并执行
接下来,看Executors中常见的几种线程池的区别
可以看到
newSingleThreadExecutor:核心线程数和最大线程数都是1,队列是LinkedBlockingQueue
newFixedThreadPool:核心线程数和最大线程数相等,超过核心线程数的空闲线程生存时间是0,队列是LinkedBlockingQueue
newCachedThreadPool:核心线程数是0,最大线程数是Integer.MAX_VALUE,空闲线程生存时间是1min,队列是SynchronousQueue
JDK1.8中的线程池的更多相关文章
- 【万字图文-原创】 | 学会Java中的线程池,这一篇也许就够了!
碎碎念 关于JDK源码相关的文章这已经是第四篇了,原创不易,粉丝从几十人到昨天的666人,真的很感谢之前帮我转发文章的一些朋友们. 从16年开始写技术文章,到现在博客园已经发表了222篇文章,大多数都 ...
- android中的线程池学习笔记
阅读书籍: Android开发艺术探索 Android开发进阶从小工到专家 对线程池原理的简单理解: 创建多个线程并且进行管理,提交的任务会被线程池指派给其中的线程进行执行,通过线程池的统一调度和管理 ...
- Java5中的线程池实例讲解
Java5增加了新的类库并发集java.util.concurrent,该类库为并发程序提供了丰富的API多线程编程在Java 5中更加容易,灵活.本文通过一个网络服务器模型,来实践Java5的多线程 ...
- Spring中的线程池和定时任务功能
1.功能介绍 Spring框架提供了线程池和定时任务执行的抽象接口:TaskExecutor和TaskScheduler来支持异步执行任务和定时执行任务功能.同时使用框架自己定义的抽象接口来屏蔽掉底层 ...
- jdk1.7中的常量池
在探究jdk1.7中的常量池,我们可以先看看以下的这段代码 public static void main(String[] args) throws Throwable { List<Stri ...
- 探究ElasticSearch中的线程池实现
探究ElasticSearch中的线程池实现 ElasticSearch里面各种操作都是基于线程池+回调实现的,所以这篇文章记录一下java.util.concurrent涉及线程池实现和Elasti ...
- 使用concurrent.futures模块中的线程池与进程池
使用concurrent.futures模块中的线程池与进程池 线程池与进程池 以线程池举例,系统使用多线程方式运行时,会产生大量的线程创建与销毁,创建与销毁必定会带来一定的消耗,甚至导致系统资源的崩 ...
- C#中的线程池使用(一)
1 线程池的概念 许多应用程序使用多个线程,但这些线程经常在休眠状态中耗费大量的时间来等待事件发生.其他线程可能进入休眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态.为了简化 ...
- mina2中的线程池
一.Mina中的线程池模型 前面介绍了Mina总体的层次结构,那么在Mina里面是怎么使用Java NIO和进行线程调度的呢?这是提高IO处理性能的关键所在.Mina的线程调度原理主要如下图所示: A ...
随机推荐
- 【技术分析】DowginCw病毒家族解析
作者:钱盾反诈实验室 0x1.背景 近期,钱盾反诈实验室通过钱盾恶意代码智能监测引擎感知并捕获一批恶意应用.由于该批病毒会联网加载"CWAPI"插件,故将其命名为"D ...
- 浏览器正确理解和使用GBK及UTF-8(UTF-8 + BOM)网页编码
网页编码英文译为web page encoding.是在网页中指定其特定的字符编码格式的库. GBK是国家标准GB2312基础上扩容后兼容GB2312的标准. GBK的文字编码是用双字节来表示的.即不 ...
- Struts2 2.5.12的问题
使用maven搭建的Struts项目,使用Struts 2.5.12会启动报错,应该不是包冲突的问题,感觉是lang3.jar的问题,换回2.5.10.1就没事了. 这点挺奇怪的,不应该是jar包损坏 ...
- 转:java泛型
1.为什么需要泛型 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52230032 泛型在Java中有很重要的地位,网上很多文章罗列各 ...
- intellij idea 下载及安装破解--好使
Intellij IDEA 14.1 提供两个版本,我下载的是旗舰版的 官方下载地址 https://www.jetbrains.com/idea/download/ 百度网盘下载地址 http:// ...
- .net 裁剪图片(不压缩)
命名空间: using System.Drawing; using System.Drawing.Imaging; /// <summary> /// 生成图片缩略文件 /// </ ...
- 三十天学不会TCP,UDP/IP网络编程-UDP,从简单的开始
如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,欢迎去gitbook(https://www.gitbook.com/@rogerzhu/)star我的这一系列文章,虽然说现在这种 ...
- docker入门【1】
1.拉取镜像 docker pull 镜像名:版本号 例如:docker pull tomcat:7.0 默认会从docker官方镜像库拉取,不指定版本的话版本为latest 拉取后docker im ...
- seleniumPO模式
一.框架目录结构 二.代码 2.1page层代码 package com.mianshui.page; import org.openqa.selenium.WebElement; import or ...
- iOS 数据加密方案
iOS安全攻防(二十三):Objective-C代码混淆 提交用户的隐私数据 一定要使用POST请求提交用户的隐私数据GET请求的所有参数都直接暴露在URL中请求的URL一般会记录在服务器的访问日志中 ...










