一、准备
YML文件中配置线程池参数
# 线程池配置
thread:
pool:
core-pool-size: 5 # 核心线程池大小,即线程池中保留的线程数
max-pool-size: 10 # 线程池最大大小,即线程池中允许的最大线程数。
queue-capacity: 50 #线程池队列容量,即在核心线程池满员的情况下,允许排队等待执行的任务数量。
keep-alive-seconds: 60 #非核心线程的存活时间,即在没有任务需要执行时,非核心线程的最大空闲时间。
获取参数
/**
* 线程池参数
*
* @author DarkClouds
* @date 2023/05/19
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "thread.pool")
public class ThreadPoolProperties {
/**
* 核心线程池大小
*/
private int corePoolSize;
/**
* 最大可创建的线程数
*/
private int maxPoolSize;
/**
* 队列最大长度
*/
private int queueCapacity;
/**
* 线程池维护线程所允许的空闲时间
*/
private int keepAliveSeconds;
}
编写线程池配置类
/**
* 线程池配置
*
* @author DarkClouds
* @date 2023/05/19
*/
@Configuration
@RequiredArgsConstructor
public class ThreadPoolConfig {
private final ThreadPoolProperties threadPoolProperties;
/**
* 创建线程池
*
* @return 线程池
*/
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心线程池大小
executor.setCorePoolSize(threadPoolProperties.getCorePoolSize());
// 最大可创建的线程数
executor.setMaxPoolSize(threadPoolProperties.getMaxPoolSize());
// 等待队列最大长度
executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
// 线程池维护线程所允许的空闲时间
executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
/**
* 执行周期性或定时任务
* 创建了一个名为 "scheduledExecutorService" 的 Bean,
* 它返回一个 ScheduledThreadPoolExecutor 对象。
* 该线程池的核心线程数由 threadPoolProperties.getCorePoolSize() 决定,
* 线程名的格式为 "schedule-pool-%d",
* 使用了 CallerRunsPolicy 策略来处理超出线程池容量的任务。
* 此外,它还重写了 ScheduledThreadPoolExecutor 的 afterExecute 方法,
* 在任务执行完成后打印异常信息。
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService() {
return new ScheduledThreadPoolExecutor(threadPoolProperties.getCorePoolSize(),
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
new ThreadPoolExecutor.CallerRunsPolicy()) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
ThreadUtils.printException(r, t);
}
};
}
}
工具类
/**
* 线程工具类
*
* @author DarkClouds
* @date 2023/05/19
*/
public class ThreadUtils {
private static final Logger logger = LoggerFactory.getLogger(ThreadUtils.class);
private static final long OVERTIME = 120;
/**
* 停止线程池
* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
* 如果仍然超時,则強制退出.
* 另对在shutdown时线程本身被调用中断做了处理.
*/
public static void shutdownAndAwaitTermination(ExecutorService pool) {
if (pool != null && !pool.isShutdown()) {
pool.shutdown();
try {
if (!pool.awaitTermination(OVERTIME, TimeUnit.SECONDS)