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线程池实现原理!>,作者:小傅哥 ...
随机推荐
- java基础知识(6)---抽象类与接口
抽象类: abstract抽象:不具体,看不明白.抽象类表象体现.在不断抽取过程中,将共性内容中的方法声明抽取,但是方法不一样,没有抽取,这时抽取到的方法,并不具体,需要被指定关键字abstract所 ...
- sublime text 侧边栏样式修改
安装PackageResourceViewer 插件.快捷键 CTRL+SHIFT+P 打开 命令面板,输入 Package Control:Install Package (直接输入PCIP,四个单 ...
- Dapper 存储过程、事务等
接上一篇<Dapper 增删改查> 0.存储过程 create proc p_login ), ), ) output as begin if(exists(select * from U ...
- OpenStack API映射分析
Nova代码阅读 确定服务类型 RPC服务 WSGI服务 查询cmd目录下的对应的服务启动脚本,根据服务创建方式来判断服务类型,service.WSGIService表示WSGI服务,service. ...
- libguestfs知识点
libguestfs 是一组 Linux 下的 C 语言的 API ,用来访问虚拟机的磁盘映像文件.其项目主页是http://libguestfs.org/ , 该工具包内包含的工具有virt-cat ...
- Java中Method.invoke方法,反射?
正常来说,我们调用对象的方法是通过dot运算符来进行的,这里我们介绍另一种方法,有以下几个步骤:1,获取该类的Class Type:2,通过getMethod方法获取Method对象:3,通过调用in ...
- CodeForces 125D【鸽巢原理】
哇塞?开始的三个数其中两个数一定能确定一个序列.(鸽巢原理) #include <bits/stdc++.h> using namespace std; typedef long long ...
- linux系统elementray os的环境搭建
因为我在使用过程中为了改变终端的外表,结果把/ect/psswd,以及/ect/profile中的文件配置修改之后,我把gnome-terminal的python脚本打包放在/bin/目录下,修改了/ ...
- Cogs 1435. [USACO NOV]金发姑娘和N头牛
1435. [USACO NOV]金发姑娘和N头牛 ★★☆ 输入文件:milktemp.in 输出文件:milktemp.out 简单对比时间限制:1 s 内存限制:256 MB [题 ...
- 带权并查集【bzoj3362】: [Usaco2004 Feb]Navigation Nightmare 导航噩梦
[bzoj]3362: [Usaco2004 Feb]Navigation Nightmare 导航噩梦 农夫约翰有N(2≤N≤40000)个农场,标号1到N,M(2≤M≤40000)条的不同的垂 ...