Spring Boot 2.0.2自定义TaskExecutor线程池不生效,生成大量线程问题
Hey 兄弟,我来帮你搞定这个问题!你遇到的情况是Spring Boot默认的@Async没自动用上你自定义的ThreadPoolTaskExecutor,而是 fallback到了SimpleAsyncTaskExecutor,所以才会冒出一堆默认线程。咱们一步步排查解决:
问题根源
Spring的@Async注解默认会用SimpleAsyncTaskExecutor(就是那些没你自定义前缀的线程),除非你明确告诉它要用你配置的线程池。另外,你的ThreadConfig类如果没加@Configuration注解,Spring根本不会把你的线程池Bean注册到容器里,这是最容易踩的坑!
解决步骤
1. 给配置类加上@Configuration注解
首先,你的ThreadConfig必须被Spring识别为配置类,所以加上@Configuration:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.core.task.TaskExecutor; @Configuration // 这个注解不能少! public class ThreadConfig { @Bean public TaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(2); executor.setMaxPoolSize(3); executor.setQueueCapacity(3); executor.setThreadNamePrefix("anniversary"); executor.initialize(); System.out.println("******* name " + executor.getThreadNamePrefix()); System.out.println("********** core pool size " + executor.getCorePoolSize()); return executor; } }
2. 让@Async知道要用你的线程池
有两种简单的方式:
方式一:把自定义线程池Bean命名为"taskExecutor"
Spring的@Async默认会优先查找名为taskExecutor的Bean,所以直接给你的Bean指定这个名字:
@Bean(name = "taskExecutor") // 指定Bean名称为taskExecutor public TaskExecutor threadPoolTaskExecutor() { // 你的线程池配置代码不变 }
这样不用改任何@Async的使用代码,它会自动用你的自定义线程池。
方式二:在@Async注解里指定线程池Bean名
如果不想改Bean的名字,就在使用@Async的时候明确指定要用到的线程池:
@Async("threadPoolTaskExecutor") // 这里填你自定义Bean的方法名或者Bean名称 public void yourAsyncTaskMethod() { // 你的异步任务逻辑 }
3. 确保启动类加了@EnableAsync注解
最后别忘了,Spring Boot的启动类必须加上@EnableAsync,不然@Async注解根本不会生效!比如:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableAsync // 这个注解一定要加! public class YourSpringBootApplication { public static void main(String[] args) { SpringApplication.run(YourSpringBootApplication.class, args); } }
验证
启动项目后运行你的异步任务,看日志里的线程名称,如果是anniversary-1、anniversary-2这种带你自定义前缀的,就说明成功用上你配置的线程池啦!
内容的提问来源于stack exchange,提问作者richard
相关产品推荐
相关产品推荐

