ThreadPoolExecutor 入参 corePoolSize 和 maximumPoolSize 的联系
前言
我们可以通过 java.util.concurrent.ThreadPoolExecutor 来创建一个线程池:
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, milliseconds, runnableTaskQueue, threadFactory, handler);
参数说明:
1、corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads方法,线程池会提前创建并启动所有基本线程。
2、maximumPoolSize(线程池最大数量):线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是,如果使用了无界的任务队列这个参数就没用了。
3、keepAliveTime(线程活动时间):线程池的工作线程空闲后,保持存活的时间。所以如果任务很多,并且每个任务执行的时间比较短,可以调大时间,提高线程利用率。
4、TimeUnit(线程活动时间的单位):可选的单位有天(Days)、小时(HOURS)、分钟(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和纳秒(NANOSECONDS,千分之一微秒)
5、runnableTaskQueue(任务队列):用于保存等待执行的任务的阻塞队列。 可以选择以下几个阻塞队列:
(1)ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,FIFO(先进先出)。
(2)LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue,静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
(3)SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool()使用了这个队列。
(4)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
6、threadFactory:用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字。
7、RejectedExecutionHandler (饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略还处理新提交的任务。它可以有如下四个选项:
AbortPolicy:直接抛出异常,默认情况下采用这种策略
CallerRunsPolicy:只用调用者所在线程来运行任务
DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
DiscardPolicy:不处理,丢弃掉
按照一般的理解,初始化线程池,只需要一个 maximumPoolSize 入参就行了,corePoolSize 和 maximumPoolSize 似乎有重复的嫌疑(一开始我也是这么以为的),其实不是这样的,下面我们来详细说说这两者的区别和联系。
要理解 这两个参数的区别,首先要知道,关于 ThreadPoolExecutor 相关的任务线程,它包含两部分:(1)正在线程池中运行的任务线程、(2)在taskQueue 中排队等待运行的任务线程。
1、当线程池初始化完成之后,executorService.submit(new Thread(...)); 加入需要运行的任务线程,因为线程池初始化是没有线程运行的,所以当提交一个任务到线程池时,线程池会创建一个线程来直接执行任务;
2、当线程池中正在运行的线程达到 corePoolSize 个时,线程会放到 taskQueue 中排队等候;
3、当 taskQueue(阻塞队列)的容量达到上限(即队列中不能再加入任务线程了),而当前的poolSize(就是正在线程池中运行的任务线程个数)小于 maximumPoolSize 时,则新增线程来处理任务;
4、当 taskQueue 的容量达到上限,且 poolSize = maximumPoolSize,那么线程池已经达到极限,会根据饱和策略RejectedExecutionHandler拒绝新的任务。
这个过程,像极了小朋友做客的场景:
小朋友做客,桌上放了一桌的土豆条,小朋友有一个碗(任务队列 taskQueue),碗里可以放10根土豆条(taskQueue容量 = 10),正常情况下,小朋友每次可以吃2根土豆条(嘴巴就是线程池,corePoolSize = 2),小朋友狼吞虎咽的吃每次可以吃4根土豆条(maximumPoolSize = 4)。
坐在餐桌边后,小朋友开始吃土豆,先往嘴里放了2根土豆条,但怕其他小朋友和自己抢,然后赶紧往自己的碗里加土豆条(加入队列),直到碗满了(现在小朋友嘴里2个土豆条,碗里10个土豆条)。小朋友依然害怕因为自己动作慢比其他人少吃,但是碗已经满了,所以小朋友开始狼吞虎咽地吃(嘴里同时塞4个土豆条,碗里10个土豆条)。此时小朋友已经达到极限了,虽然桌上还有土豆条,但是也只能先拒绝了(饱和策略RejectedExecutionHandler),等嘴巴里的土豆条吃完之后,再去取。
补充:
如果 使用 LinkedBlockingQueue(使用无入参构造) 对象作为 taskQueue,则不容易出现队列满情况,而容易出现内存溢出情况。
ThreadPoolExecutor 入参 corePoolSize 和 maximumPoolSize 的联系的更多相关文章
- ThreadPoolExecutor的corePoolSize和maximumPoolSize
按照JDK文档的描述, 如果池中的实际线程数小于corePoolSize,无论是否其中有空闲的线程,都会给新的任务产生新的线程 如果池中的线程数>corePoolSize and <max ...
- 理解ThreadPoolExecutor线程池的corePoolSize、maximumPoolSize和poolSize
我们知道,受限于硬件.内存和性能,我们不可能无限制的创建任意数量的线程,因为每一台机器允许的最大线程是一个有界值.也就是说ThreadPoolExecutor管理的线程数量是有界的.线程池就是用这些有 ...
- 线程池的corePoolSize、maximumPoolSize和poolSize
什么是线程池: 为了避免系统频繁的创建和销毁线程,我们可以将创建的线程进行复用.在线程池中总有那么几个活跃的线程,也有一定的最大值限制,一个业务使用完线程之后,不是立即销毁而是将其放入到线程池中,从而 ...
- js的replace函数入参为function时的疑问
近期在写js导出excel文件时运用到replace方法,此处详细的记录下它各个参数所代表的的意义. 定义和用法 replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式 ...
- springMVC中 request请求数据绑定到Controller入参 过程剖析
前言:Controller方法的参数类型可以是基本类型,也可以是封装后的普通Java类型.若这个普通Java类型没有声明任何注解,则意味着它的每一个属性都需要到Request中去查找对应的请求参数.众 ...
- XmlRpc.net 入参结构体嵌套的转义操作
项目使用C#开发,需要使用XmlRpc和Linux服务器端交互,用的是XmlRpc.net. 普通的程序调用入参和出差都没有问题,今天遇到入参结构体嵌套,结果 args 入参在服务器端不能解析.抓包数 ...
- 解决WebApi入参时多对象的问题
我们的项目是用WebApi提供数据服务,且WebPage跟APP中都有调用到. WebApi提供的接口一多,就发现一个问题,我们项目中有很多接口是接收POST(安全原因,我们采用的是https)请求的 ...
- URL类型入参串调用接口
最近通过调用另一个合作公司提供的接口实现方法,借鉴同事之前编写的方法 Models.JSON.Patient类中有各种属性,也可增加属性来满足新需求 public string TakeAppoint ...
- C#构造函数在继承时必须要求与父类型构造函数入参相同怎么办?
摘要 我们都知道,C#中,在类型继承时,由于构造子类必须先构造其父类型的内容,因此,必须子类型的构造函数中调用父类型的构造函数(无参数的不需要显式声明). 但是往往我们会出现,子类型本身的构造函数大于 ...
随机推荐
- Confluence 6 已经存在的安装配置数据库字符集编码
针对已经存在的 Confluence 安装,如果你安装的 Confluence 版本是 6.4 或者早期的版本,我们在安装的时候没有检查你数据库的字符设置. 如果你的数据库当前没有被配置使用 UTF- ...
- Spark Streaming 实现思路与模块概述
一.基于 Spark 做 Spark Streaming 的思路 Spark Streaming 与 Spark Core 的关系可以用下面的经典部件图来表述: 在本节,我们先探讨一下基于 Spark ...
- MySQL监控系统Lepus的搭建
现在流行的监控系统很多,选择一个合适自己的就可以了,例如Zabbix.Nagios:监控MySQL为主的有MySQLMTOP.Lepus.本文主要介绍快速部署lepus以及监控MySQL,因为作为DB ...
- Django复习
django复习 django和其他框架的对比 django,集成很多功能的大型框架,为开发者提供了很多方便的组件:orm.form.ModelForm.auth.admin.contenttypes ...
- 关于使用summernote编辑器提示内容无法汉化临时解决办法
原因:使用汉化summernote-zh-CN.js文件无法汉化 $('#summernote').summernote({ lang: 'zh-CN' }); 解决方法: 打开summernote. ...
- file按钮美化成图片(纯HTML+CSS)
效果图: 代码实现: html: <div> <h2>上传头像</h2> <p class="fs18">(请上传200X200px ...
- 原生开发小程序 和 wepy 、 mpvue, Taro 对比
https://blog.csdn.net/yang450712123/article/details/79623518 mpvue https://www.cnblogs.com/bgwhite/p ...
- hadoop集群运行jps命令以后Datanode节点未启动的解决办法
出现该问题的原因:在第一次格式化dfs后,启动并使用了hadoop,后来又重新执行了格式化命令(hdfs namenode -format),这时namenode的clusterID会重新生成,而da ...
- [转] 2016 JavaScript 发展现状大调查
有人认为JavaScript是最好的语言,有人认为它一团糟.可按照C++之父的话来讲: 世界上只有两种编程语言:一种是天天被人喷的,另一种是没人用的. 不论你喜欢承认与否,JavaScript已经一天 ...
- HDU 1074 Doing Homework(DP状态压缩)
题意:有n门功课需要完成,每一门功课都有时间期限以及你完成所需要的时间,如果完成的时间超出时间期限多少单位,就会被减多少学分,问以怎样的功课完成顺序,会使减掉的学分最少,有多个解时,输出功课名字典序最 ...