使用Spring的线程池实现优雅关机

189 阅读2分钟

ThreadPoolTaskExecutor

这是 Spring 提供的一个线程池实现,基于 Java 的 ThreadPoolExecutor,可以方便地进行配置和使用。它支持 Spring 的任务调度和异步处理。

@Configuration
public class ThreadPoolConfig {

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("MyExecutor-");
        executor.initialize();
        return executor;
    }
}

如何实现项目关闭后,执行完线程池中的任务?

由于我们用的就是spring管理的线程池,那么实现优雅关机就非常的简单,只需要将WaitForTasksToCompleteOnShutdown 改成 true 即可,默认是false

什么原理?

因为,当项目关闭的时候,需要通过jvm的shutdownHook回调线程池,等队列里任务执行完再停机。保证任务不丢失。

shutdownHook会回调Spring容器,Spring实现的线程池实现了DisposableBeandestroy方法,可以从下图看到最终会调用executor.shutdown()方法

调用了shutdown()方法会发生什么,这不得不说说线程池状态的流转了。

  • RUNNING: 接收新任务并处理已提交的任务。此状态是线程池的正常工作状态。
  • SHUTDOWN: 不再接收新任务,但会处理任务队列中的任务。 可以通过调用 shutdown() 方法进入此状态。
  • STOP: 不再接收新任务,不会处理任务队列中的任务,并且会中断正在执行的任务。通过调用 shutdownNow() 方法进入此状态。
  • TERMINATED: 所有任务都已完成,且线程池已完全关闭。线程池在进入 TERMINATED 状态后,无法再恢复。

所以,调用了shutdown()方法,就可以在项目关闭的时候,会处理完任务队列中的任务。

示例代码

@Configuration
public class ThreadPoolConfig {

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 程序停止后,线程池中的任务执行完后才关闭(优雅关机)
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("MyExecutor-");
        
        executor.initialize();
        return executor;
    }
}