线程池参数设置问题

JDK1.5中引入了强大的concurrent包,线程池的实现ThreadPoolExcutor。

系统负载

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

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

ThreadPoolExcutor类可设置的参数有:

1.corePoolSize:

    核心线程数,核心线程会一直存活,即使没有任务需要处理。当线程数小于核心线程数时,即使现有的线程空闲,线程池也会优先创建新线程来处理任务,而不是直接交给现有的线程处理;

    核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认情况下不会退出。

    每个任务需要tasktime秒处理,则每个线程每秒可以处理1/tasktime个任务。系统每秒有tasks个任务,所以需要的线程数为tasks/(1/tasktime),即tasks*tasktime个线程数。

    假设系统每秒任务数为100-1000,每个任务耗时0.1秒,那么需要10-100个线程, 核心线程数应设置为大于10,具体数字最好根据8020原则,即80%情况下系统每秒任务数,若系统80%情况下每秒任务数小于200,最多时为1000,那么可以设置为20。

2.maxPoolSize:

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

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

3.keepAliveTime:

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

4.allowCoreThreadTimeout:

    是否允许核心线程空闲退出。

5.queueCapacity:

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

    任务队列的长度要根据核心线程数,以及系统对任务响应时间的要求有关。队列长度可以设置为:

(corePoolSize/tasktime)*responsetime:20/0.1*2=400,即队列长度可以设置为400。

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

LinkedBlockingQueue queue=new LinkedBlockingQueue();

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

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

参考:https://blog.csdn.net/zhouhl_cn/article/details/7392607

猜你喜欢

转载自blog.csdn.net/hellodake/article/details/81974686