ThreadPoolExecutor线程池的keepAliveTime
keepAliveTime含义
看了很多文章觉得都不能把keepAliveTime的意思说的很明白,希望通过自己的理解把keepAliveTime说的明确一些
先引用一句我觉得相对说的比较明白的含义:当线程空闲时间达到keepAliveTime,该线程会退出,有两个疑问:1、线程为什么会空闲 2、线程为什么要退出
如果我们不能把线程池各个参数的来龙去脉都梳理清楚其实是很难明白keepAliveTime的含义的
我们来举例说明:
核心线程数10,最大线程数30,keepAliveTime是3秒
随着任务数量不断上升,线程池会不断的创建线程,直到到达核心线程数10,就不创建线程了,
这时多余的任务通过加入阻塞队列来运行,
当超出阻塞队列长度+核心线程数时,
这时不得不扩大线程个数来满足当前任务的运行,这时就需要创建新的线程了(最大线程数起作用),上限是最大线程数30
那么超出核心线程数10并小于最大线程数30的可能新创建的这20个线程相当于是“借”的,如果这20个线程空闲时间超过keepAliveTime,就会被退出
我们来看开头提到的两个问题:
1、线程为什么会空闲
2、线程为什么要退出
答:
1、没有任务时线程就会空闲下来,在线程池中任务是任务(Runnale)线程是线程(Worker)
2、通常超出核心线程的线程是“借”的,也就是说超出核心线程的情况算是一种能够预见的异常情况,并且这种情况并不常常发生(如果常常发生,那我想你应该调整你的核心线程数了),所以这种不经常发生而创建的线程为了避免资源浪费就应该要退出
我们需要看一下java.util.concurrent.ThreadPoolExecutor#getTask源码来验证上面一段话的含义:
int wc = workerCountOf(c);
// Are workers subject to culling? 是否屠宰workers
//当allowCoreThreadTimeOut为true或者当前任务数超过核心线程数时,timed为true
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
……
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) ://如果timed为true说明worker有可能要被关闭,这里调用的代码含义:如果超过keepAliveTime纳秒还没取到任务,就返回null,后面会调用processWorkerExit把worker关闭
workQueue.take();//否则任务队列为空就阻塞在这里,直到任务队列再有任务
if (r != null)
return r;
10个核心线程会不会退出,由下面的参数决定:
allowCoreThreadTimeout:是否允许核心线程空闲退出,默认值为false
当keepAliveTime设置为0时到底是空闲线程直接退出还是不退出
通过实验证明和上文代码workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)证明,是直接不等待退出,而不是永远不退出
这样我们就需要注意了,这个值设置为0 并不是个很好的做法(除非场景中任务数量极少能超出核心线程数),如果任务数频繁超出核心线程数,这个值需要评估设定为合理值尽量避免线程开启关闭的动作

(上图,如果永远不退出,那么workers就不是10 而是45)
ThreadPoolExecutor线程池的keepAliveTime的更多相关文章
- ThreadPoolExecutor 线程池的源码解析
1.背景介绍 上一篇从整体上介绍了Executor接口,从上一篇我们知道了Executor框架的最顶层实现是ThreadPoolExecutor类,Executors工厂类中提供的newSchedul ...
- j.u.c系列(01) ---初探ThreadPoolExecutor线程池
写在前面 之前探索tomcat7启动的过程中,使用了线程池(ThreadPoolExecutor)的技术 public void createExecutor() { internalExecutor ...
- Java并发——ThreadPoolExecutor线程池解析及Executor创建线程常见四种方式
前言: 在刚学Java并发的时候基本上第一个demo都会写new Thread来创建线程.但是随着学的深入之后发现基本上都是使用线程池来直接获取线程.那么为什么会有这样的情况发生呢? new Thre ...
- ThreadPoolExecutor 线程池
TestThreadPoolExecutorMain package core.test.threadpool; import java.util.concurrent.ArrayBlockingQu ...
- 十、自定义ThreadPoolExecutor线程池
自定义ThreadPoolExecutor线程池 自定义线程池需要遵循的规则 [1]线程池大小的设置 1.计算密集型: 顾名思义就是应用需要非常多的CPU计算资源,在多核CPU时代,我们要让每一个CP ...
- Executors、ThreadPoolExecutor线程池讲解
官方+白话讲解Executors.ThreadPoolExecutor线程池使用 Executors:JDK给提供的线程工具类,静态方法构建线程池服务ExecutorService,也就是Thread ...
- 手写线程池,对照学习ThreadPoolExecutor线程池实现原理!
作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...
- 源码剖析ThreadPoolExecutor线程池及阻塞队列
本文章对ThreadPoolExecutor线程池的底层源码进行分析,线程池如何起到了线程复用.又是如何进行维护我们的线程任务的呢?我们直接进入正题: 首先我们看一下ThreadPoolExecuto ...
- 手写一个线程池,带你学习ThreadPoolExecutor线程池实现原理
摘要:从手写线程池开始,逐步的分析这些代码在Java的线程池中是如何实现的. 本文分享自华为云社区<手写线程池,对照学习ThreadPoolExecutor线程池实现原理!>,作者:小傅哥 ...
随机推荐
- DTP模型之一:(XA协议之一)XA协议、二阶段2PC、三阶段3PC提交
XA协议 XA是一个分布式事务协议,由Tuxedo提出.XA中大致分为两部分:事务管理器和本地资源管理器.其中本地资源管理器往往由数据库实现,比如Oracle.DB2这些商业数据库都实现了XA接口,而 ...
- linux使用JMETER进行分布式压力测试
1. 下载jmeter tgz文件 http://jmeter.apache.org/download_jmeter.cgi 2. 登录linux服务器,创建jmeter目录,rz上传jmeter ...
- <正则吃饺子> :关于使用pd创建表时需要注意的地方
公司项目使用pd设计数据库表.之前用过,但是年代比较久远了,有些细节忘记了,今天重新使用时候,生疏了,现在稍微记录下吧. 1.pd创建表的使用,可以直接从网上搜索,博文比较多,如 “pd 设计数据库表 ...
- linux命令-tar工具详解
把文件和目录打成一个包 文件打包 [root@wangshaojun ~]# tar -cvf 1.tar 1.txt 123 234 ///-c创建 -v可视化 -f file放最后面1.txt12 ...
- .net 缓存之应用程序数据缓存
CaCheHelp类中代码如下: #region 根据键从缓存中读取保持的数据 /// <summary> /// 根据键从缓存中读取保持的数据 /// </summary> ...
- shell分库备份
分库备份企业实战题7:如何实现对MySQL数据库进行分库备份,请用脚本实现 #!/bin/bash MysqlUser=root PassWord=root Port= Socket="/u ...
- Windchill 基本业务对象
容器容器是Windchill对象存放的地方:在Windchill中主要的容器有站点.组织.产品.存储库.项目.在Windchill中所有容器对象的父类为wt.inf.container.WTConta ...
- 主线程与UI线程简介
---------------siwuxie095 Java 程序的主线程 当 Java 程序启动时,一个线程立刻运行,该线程通常叫做程 ...
- 5、bam格式转为bigwig格式
1.Bam2bigwig(工具) https://www.researchgate.net/publication/301292288_Bam2bigwig_a_tool_to_convert_bam ...
- 6.1 安装Ubuntu
声明:sunny从来没有接触过linux.今天是第一次接触linux,日后每天都会接触linux了.坚持,每日练习,相信毕业后的我,一定会从小白成为linux大神. 安装Ubuntu之前,请先参考该博 ...