java线程池配置详解

java线程池配置详解

网络资料多是复制粘贴,在此重写,以我为准。

结论

  • 4核

    // 核心线程池大小
    private int corePoolSize = 20;
    
    // 最大可创建的线程数
    private int maxPoolSize = 80;
    
    // 队列最大长度
    private int queueCapacity = 400;
    
    // 线程池维护线程所允许的空闲时间
    private int keepAliveSeconds = 200;
  • 2核

    // 核心线程池大小
    private int corePoolSize = 10;
    
    // 最大可创建的线程数
    private int maxPoolSize = 40;
    
    // 队列最大长度
    private int queueCapacity = 200;
    
    // 线程池维护线程所允许的空闲时间
    private int keepAliveSeconds = 100;
  • 1核

    // 核心线程池大小
    private int corePoolSize = 5;
    
    // 最大可创建的线程数
    private int maxPoolSize = 20;
    
    // 队列最大长度
    private int queueCapacity = 100;
    
    // 线程池维护线程所允许的空闲时间
    private int keepAliveSeconds = 50;

参数说明

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

  • corePoolSize

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

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

  • maxPoolSize

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

  • keepAliveSeconds

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

  • allowCoreThreadTimeout

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

  • queueCapacity

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

扩容流程:

线程池

参数配置

corePoolSize

任务主要分为两类计算密集型IO密集型

目前大多数cpu都是多核多线程,像我是6核12线程,因此以往的用cpu核数计算并不恰当,应以实际线程数为主。

注意:有些cpu说是4核8线程,但实际上是6线程+2虚拟线程,此时要用6来计算。

或者直接一把梭:Runtime.getRuntime().availableProcessors()

在计算corePoolSize时涉及到一个阻塞系数的概念。

如果任务有50%的时间处于阻塞状态,则阻塞系数为0.5。则程序所需的线程数为处理器可用核心数的两倍。如果任务被阻塞的时间少于50%,即这些任务是计算密集型的,则程序所需线程数将随之减少,但最少也不应该低于处理器的核心数。如果任务被阻塞的时间大于执行时间,即该任务是IO密集型的,我们就需要创建比处理器核心数大几倍数量的线程。

计算公式:线程数 =cpu实际线程数/(1 - 阻塞系数),其中阻塞系数的取值在0和1之间。计算密集型人物的阻塞系数为0,而IO密集型任务的阻塞系数则接近1。

通用的说,计算密集型的corePoolSize=cpu实际线程数+1

IO密集型的corePoolSize=cpu实际线程数*5

queueCapacity

任务队列的长度要根据核心线程数,以及系统对任务响应时间的要求有关。队列长度计算公式为(corePoolSize/tasktime)*responsetime。

一般来说,tasktime是0.1,responsetime是2,因此等价于

queueCapacity=20*corePoolSize

maxPoolSize

如果需要最大线程池扩容,则说明任务队列已满。在这种情况下,对于计算密集型的任务,扩容线程池意义不是很大,因为不需要上下文的切换,这种情况下建议增加物理核数;对于IO密集型的任务,说明IO的速度变慢,需要将空闲的cpu资源让给后续的线程,需要增加线程池的容量。

一般来说,我们设置为core的4倍。

maxPoolSize=4*corePoolSize

keepAliveTime

此参数设置的最大意义是当线程池维持在一个较高的使用率,延长线程存活时间可以有效的提高处理速度,避免无用的创建-销毁线程。

keepAliveTime = 5*responsetime * corePoolSize

allowCoreThreadTimeout

此参数建议维持默认false,不建议核心线程也退出。


java线程池配置详解
https://note.0moe.cn/Java/2020/05/27/java线程池配置详解/
作者
Dawn_南风
发布于
2020年5月27日
许可协议