线程池参数详解

线程池参数详解转载来自:http://blog.csdn.net/zhouhl_cn/article/details/7392607JDK1.5中引入了强大的concurrent包,其中最常用的莫过了线程池的实现ThreadPoolExecutor,它给我们带来了极大的方便,但同时,对于该线程池不恰当的设置也可能使其效率并不能达到预期的效果,甚至仅相当于或低于单线程的效率。ThreadPoo

大家好,又见面了,我是你们的朋友全栈君。

转载来自:http://blog.csdn.net/zhouhl_cn/article/details/7392607 和http://www.cnblogs.com/dolphin0520/p/3932921.html

JDK1.5中引入了强大的concurrent包,其中最常用的莫过了线程池的实现ThreadPoolExecutor,它给我们带来了极大的方便,但同时,对于该线程池不恰当的设置也可能使其效率并不能达到预期的效果,甚至仅相当于或低于单线程的效率。

ThreadPoolExecutor类可设置的参数主要有:

  • corePoolSize

在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,(除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,从这2个方法的名字就可以看出,是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或者一个线程)。

默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认情况下不会退出。

  • maxPoolSize

当线程数大于或等于核心线程,且任务队列已满时,线程池会创建新的线程,直到线程数量达到maxPoolSize。如果线程数已等于maxPoolSize,且任务队列已满,则已超出线程池的处理能力,线程池会拒绝处理任务而抛出异常。

  • keepAliveTime

当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize。如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0。

  • allowCoreThreadTimeout

是否允许核心线程空闲退出,默认值为false。

  • queueCapacity

任务队列容量。从maxPoolSize的描述上可以看出,任务队列的容量会影响到线程的变化,因此任务队列的长度也需要恰当的设置。

还有就是 workQueue:一个阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响,一般来说,这里的阻塞队列有以下几种选择:

ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue;
PriorityBlockingQueue 

ArrayBlockingQueue和PriorityBlockingQueue使用较少,一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。

  • threadFactory:线程工厂,主要用来创建线程;
  • handler:表示当拒绝处理任务时的策略,有以下四种取值:
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 

线程池按以下行为执行任务

  1. 当线程数小于核心线程数时,创建线程。
  2. 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
  3. 当线程数大于等于核心线程数,且任务队列已满
    1. 若线程数小于最大线程数,创建线程
    2. 若线程数等于最大线程数,抛出异常,拒绝任务

系统负载

参数的设置跟系统的负载有直接的关系,下面为系统负载的相关参数:

  • tasks,每秒需要处理的最大任务数量
  • tasktime,处理第个任务所需要的时间
  • responsetime,系统允许任务最大的响应时间,比如每个任务的响应时间不得超过2秒。

参数设置

corePoolSize:

每个任务需要tasktime秒处理,则每个线程每钞可处理1/tasktime个任务。系统每秒有tasks个任务需要处理,则需要的线程数为:tasks/(1/tasktime),即tasks*tasktime个线程数。假设系统每秒任务数为100~1000,每个任务耗时0.1秒,则需要100*0.1至1000*0.1,即10~100个线程。那么corePoolSize应该设置为大于10,具体数字最好根据8020原则,即80%情况下系统每秒任务数,若系统80%的情况下第秒任务数小于200,最多时为1000,则corePoolSize可设置为20。

queueCapacity:

任务队列的长度要根据核心线程数,以及系统对任务响应时间的要求有关。队列长度可以设置为(corePoolSize/tasktime)*responsetime: (20/0.1)*2=400,即队列长度可设置为400。

队列长度设置过大,会导致任务响应时间过长,切忌以下写法:

LinkedBlockingQueue queue = new LinkedBlockingQueue();

这实际上是将队列长度设置为Integer.MAX_VALUE,将会导致线程数量永远为corePoolSize,再也不会增加,当任务数量陡增时,任务响应时间也将随之陡增。

maxPoolSize:

当系统负载达到最大值时,核心线程数已无法按时处理完所有任务,这时就需要增加线程。每秒200个任务需要20个线程,那么当每秒达到1000个任务时,则需要(1000-queueCapacity)*(20/200),即60个线程,可将maxPoolSize设置为60。

keepAliveTime:

线程数量只增加不减少也不行。当负载降低时,可减少线程数量,如果一个线程空闲时间达到keepAliveTiime,该线程就退出。默认情况下线程池最少会保持corePoolSize个线程。

allowCoreThreadTimeout:

默认情况下核心线程不会退出,可通过将该参数设置为true,让核心线程也退出。

以上关于线程数量的计算并没有考虑CPU的情况。若结合CPU的情况,比如,当线程数量达到50时,CPU达到100%,则将maxPoolSize设置为60也不合适,此时若系统负载长时间维持在每秒1000个任务,则超出线程池处理能力,应设法降低每个任务的处理时间(tasktime)。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/134817.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 三阶魔方还原公式_三阶魔方顶层小鱼口诀

    三阶魔方还原公式_三阶魔方顶层小鱼口诀1.第二层棱块归位:2.顶层十字3.顶层棱中间块归位这一步的目的是使顶层的4个棱中间块全部归位。转动顶层(U),若可以使一个棱中间块归位(如下图左,这里以[红-黄]块为例),而其他3个都

  • 【转载】Asp.Net页面生命周期

    【转载】Asp.Net页面生命周期

    2021年11月21日
  • java:闰年判断程序[通俗易懂]

    java:闰年判断程序[通俗易懂]公历闰年的简单计算方法(符合以下条件之一的年份即为闰年)1、能被4整除而不能被100整除。2、能被400整除。方案:使用数学运算符取余运算(%),关系运算符等于(==)和不等于(!=),辑运算符逻辑与(&&)和逻辑或(||),来判断某年是否为闰年,判断的结果为boolean类型的值,如果为闰年boolean类型的值为true,否则为falsebooleanflag=(year%4==0&&year%100!=0)||year%400==0

  • Visual Studio 2022无法打开源文件[通俗易懂]

    Visual Studio 2022无法打开源文件[通俗易懂]今天遇到个很糟心的问题,安装好的VisualStudio2022无法打开多个源文件,以至于连默认的HelloWorld程序都跑不起来(如下图所示,四百多个错误)。网上找了很多办法,有修改附加包含目录的(按道理这个是对每个项目进行定制化处理的,通过将第三方库的路径插入至查找路径中以方便载入第三方库)、有修改SDK版本的(其实方向对了,但是本地没有需要的SDK再怎么修改都是枉然)、有重新安装VisualStudio的(默认添加的SDK版本是不对的,所以还是无法解决问题),但是这些方法都没用。.

  • GPIB-VC编程

    GPIB-VC编程CompilingandLinkingVISAPrograms(C/C++)Thissectionprovidesasummaryofimportantcompiler-specificconsiderationswhendevelopingWin32applications.1.LinkingtoVISALibrariesYourapp

  • sql中ddl和dml(数据库表与视图的区别)

    DDL和DML的定义和区别1、DML(DataManipulationLanguage)数据操纵语言:适用范围:对数据库中的数据进行一些简单操作,如insert,delete,update,select等.对表(索引和序列)中数据操作就是DML,对数据库中的(表,索引,序列,同义词等)都是DDL操作 2、DDL(DataDefinitionLanguage)数据定义语言:适用范围:对数据库…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号