Java 线程池优化

1. Java 线程池优化

1.1. 核心线程数

  • CPU 密集型线程池计算公式:
核心线程数 = CPU 核心数 + 1
  • IO 密集型线程池计算公式:
核心线程数 = ((线程等待时间 + 线程 CPU 时间)/线程 CPU 时间)* CPU 数目

1.2. 任务队列

java.util.concurrent.BlockingQueue 的子类大多可作为任务队列,但一般使用 java.util.concurrent.ArrayBlockingQueuejava.util.concurrent.LinkedBlockingQueuejava.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. 最终优化代码

  1. IO 密集型线程池
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();
}
}
  1. CPU 密集型线程池
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 + 1)
.setMaxPoolSize(availableProcessors +1)
.setKeepAliveTime(1L, TimeUnit.MINUTES)
.useSynchronousQueue()
.setHandler(new ThreadPoolExecutor.CallerRunsPolicy())
.setThreadFactory(ThreadUtil.createThreadFactory("my-thread-"))
.build();
}
}
posted @   Jason207010  阅读(71)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示