1. Java 线程池优化
1.1. 核心线程数
- CPU 密集型线程池计算公式:
核心线程数 = CPU 核心数 + 1
- IO 密集型线程池计算公式:
核心线程数 = ((线程等待时间 + 线程 CPU 时间)/线程 CPU 时间)* CPU 数目
1.2. 任务队列
java.util.concurrent.BlockingQueue
的子类大多可作为任务队列,但一般使用 java.util.concurrent.ArrayBlockingQueue
、java.util.concurrent.LinkedBlockingQueue
和 java.util.concurrent.SynchronousQueue
作为任务队列。
1.2.1. LinkedBlockingQueue
基于链表的阻塞队列。
调用 LinkedBlockingQueue(int capacity)
构建方法指定队列大小时,作为有界任务队列。
调用 LinkedBlockingQueue()
无参构建方法时,等价于 LinkedBlockingQueue(Integer.MAX_VALUE)
,队列大小为 2147483647
,一般任务数量达到这个数值时,程序已经 OOM 了,所以相当于无界任务队列,本质上还是有界任务队列。
1.2.2. ArrayBlockingQueue
基于数组的阻塞队列。构造方法必须指定队列大小,是有界任务队列。
1.2.3. SynchronousQueue
队列大小为 0
的阻塞队列,添加到队列的任务将立即被处理,当所有核心线程处于活动状态,线程池将新建新的线程来处理任务,直至达到最大线程数。
1.2.4. 总结
一般使用 ArrayBlockingQueue 有界阻塞队列,队列大小视实际情况而定,一般取 10000
1.3. 最大线程数
当所有核心线程均处于活动状态,并且任务队列已满,线程池才会新建新的线程来处理任务,直至所有线程达到最大线程数。
最大线程数视实际情况而定,一般取核心线程数 * 2
1.4. 线程存活时间
视实际情况而定,一般一分钟
1.5. 拒绝策略
当任务队列已满,并且线程池已达到最大线程数量时,提交任务到线程池将被拒绝。Java 定义了 4 种拒绝策略。
1.5.1. AbortPolicy(默认策略)
抛出 RejectedExecutionException 来拒绝新提交的任务。
1.5.2. CallerRunsPolicy
调用者所在的线程会尝试执行被拒绝的任务。
1.5.3. DiscardPolicy
不采取任何措施,丢弃无法处理的任务。
1.5.4. DiscardOldestPolicy
丢弃队列最前面的任务,然后尝试再次提交被拒绝的任务。
1.5.5. 总结
重要数据处理任务使用 CallerRunsPolicy,避免数据丢失。或者使用 AbortPolicy,并做好异常善后处理。
1.6. 最终优化代码
import cn.hutool.core.thread.ExecutorBuilder;
import cn.hutool.core.thread.ThreadUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Configuration
public class ThreadPoolConfiguration {
@Bean
public ThreadPoolExecutor threadPoolExecutor() {
int availableProcessors = Runtime.getRuntime().availableProcessors();
return ExecutorBuilder.create()
.setCorePoolSize(availableProcessors * 50)
.setMaxPoolSize(availableProcessors * 100)
.setKeepAliveTime(1L, TimeUnit.MINUTES)
.useArrayBlockingQueue(10_000)
.setHandler(new ThreadPoolExecutor.CallerRunsPolicy())
.setThreadFactory(ThreadUtil.createThreadFactory("my-thread-"))
.build();
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。