我是靠谱客的博主 鲜艳音响,最近开发中收集的这篇文章主要介绍springboot 自定义线程池后程序无法终止,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

背景

springboot 自定义线程池,并在ComplatedFuture.runAsync(Runnable, Executor)使用该线程池执行任务

@Configuration
public class ExecutorConfig {
private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
@Value("${spring.task.execution.pool.core-size:20}")
private int corePoolSize;
@Value("${spring.task.execution.pool.max-size:50}")
private int maxPoolSize;
@Value("${spring.task.execution.pool.queue-capacity:100}")
private int queueCapacity;
@Value("${spring.task.execution.thread-name-prefix:empf_}")
private String namePrefix;
@Value("${spring.task.execution.pool.keep-alive:3}")
private int keepAliveSeconds;
@Bean(name = "asyncServiceExecutor")
public Executor asyncServiceExecutor() {
logger.info("start asyncServiceExecutor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(corePoolSize);
//配置最大线程数
executor.setMaxPoolSize(maxPoolSize);
//配置队列大小
executor.setQueueCapacity(queueCapacity);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix(namePrefix);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setWaitForTasksToCompleteOnShutdown(true);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
@Service
public class PrintService{
@Autowired
private Executor asyncServiceExecutor;
public void printNumber(){
CompletableFuture.runAsync(() -> System.out.println(1), asyncServiceExecutor);
}
}

在运行完成程序后,springboot应用并没有结束,而是处于一直等待的状态

而当不使用自动线程池,直接注入springboot的线程池,在运行完printNumber()方法60s后,springboot应用停止

public class PrintService{
@Autowired
private Executor executor;
public void printNumber(){
CompletableFuture.runAsync(() -> System.out.println(1), asyncServiceExecutor);
}
}

问题探索

因此去查看两个线程池有何差异,其中有一个属性allowCoreThreadTimeOut 不一样,自定义线程池的为false,springboot默认线程池为true

再查看此属性的作用

package java.util.concurrent;
public class ThreadPoolExecutor{
/**
* Sets the policy governing whether core threads may time out and
* terminate if no tasks arrive within the keep-alive time, being
* replaced if needed when new tasks arrive. When false, core
* threads are never terminated due to lack of incoming
* tasks. When true, the same keep-alive policy applying to
* non-core threads applies also to core threads. To avoid
* continual thread replacement, the keep-alive time must be
* greater than zero when setting {@code true}. This method
* should in general be called before the pool is actively used.
*
* @param value {@code true} if should time out, else {@code false}
* @throws IllegalArgumentException if value is {@code true}
*
and the current keep-alive time is not greater than zero
*
* @since 1.6
*/
public void allowCoreThreadTimeOut(boolean value) {
if (value && keepAliveTime <= 0)
throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
if (value != allowCoreThreadTimeOut) {
allowCoreThreadTimeOut = value;
if (value)
interruptIdleWorkers();
}
}
}

注意这句,When false, core threads are never terminated due to lack of incoming tasks

大意就是,当 allowCoreThreadTimeOut = false 时,即使没有任务执行,核心线程也不会终止,这就可以解释为什么自定义线程池的springboot应用没办法终止

另外注意,When true, the same keep-alive policy applying to non-core threads applies also to core threads. To avoid continual thread replacement, the keep-alive time must be greater than zero when setting true.

当 allowCoreThreadTimeOut = true 时,keep-alive time 需要为正数,经过 keep-alive time 后,线程将就会自动终止

额外收获

springboot线程池创建相关的类

TaskExecutorBuilder
TaskExecutionAutoConfiguration
TaskExecutionProperties

最后

以上就是鲜艳音响为你收集整理的springboot 自定义线程池后程序无法终止的全部内容,希望文章能够帮你解决springboot 自定义线程池后程序无法终止所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部