线程池配置优化指南

墨韵云阁 7 阅读 开发笔记

线程运行规则

手动设置线程池,就要合理设置最大线程数和核心线程数,按照网上大多数的说法,都是跟服务器的CPU有关

1. 先看下机器的 CPU 核数,然后在设定具体参数:

System.out.println(Runtime.getRuntime().availableProcessors());

即 CPU 核数 = Runtime.getRuntime().availableProcessors()

  1. 分析下线程池处理的程序是 CPU 密集型,还是 IO 密集型

    1. IO 密集型:大量网络,文件操作

    2. IO 密集型:核心线程数 = CPU 核数 * 2

    3. CPU 密集型:大量计算,cpu 占用越接近 100%, 耗费多个核或多台机器

    4. CPU 密集型:核心线程数 = CPU 核数 + 1

    5. 注:IO 密集型(某大厂实践经验)

    6. 核心线程数 = CPU 核数 / (1- 阻塞系数) 例如阻塞系数 0.8,CPU 核数为 4,则核心线程数为 20

maxPoolSize

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

keepAliveTime

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

allowCoreThreadTimeout

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

queueCapacity

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

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

LinkedBlockingQueue queue = new LinkedBlockingQueue();

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