上周发了一篇关于Spring Boot中使用@Async
来实现异步任务和线程池控制的文章: 《Spring Boot使用@Async实现异步调用:自定义线程池》。由于最近身边也发现了不少异步任务没有正确处理而导致的不少问题,所以在本文就接前面内容,继续说说线程池的优雅关闭,主要针对ThreadPoolTaskScheduler
线程池。
问题现象
在上篇文章的例子Chapter4-1-3中,我们定义了一个线程池,然后利用@Async
注解写了3个任务,并指定了这些任务执行使用的线程池。在上文的单元测试中,我们没有具体说说shutdown相关的问题,下面我们就来模拟一个问题现场出来。
第一步:如前文一样,我们定义一个ThreadPoolTaskScheduler
线程池:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@EnableAsync
@Configuration
class TaskPoolConfig {
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
executor.setPoolSize(20);
executor.setThreadNamePrefix("taskExecutor-");
return executor;
}
}
}
第二步:改造之前的异步任务,让它依赖一个外部资源,比如:Redis
@Slf4j
@Component
public class Task {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Async("taskExecutor")
public void doTaskOne() throws Exception {
log.info("开始做任务一");
long start = System.currentTimeMillis();
log.info(stringRedisTemplate.randomKey());
long end = System.currentTimeMillis();
log.info("完成任务一,耗时:" +