【问题标题】:Shutdown of Executor service in Spring Boot when Tomcat shuts downTomcat关闭时Spring Boot中Executor服务的关闭
【发布时间】:2019-02-15 20:55:41
【问题描述】:

我在Spring Boot中配置了一个执行器服务如下:

@Configuration
@PropertySource({ "classpath:executor.properties" })
public class ExecutorServiceConfig {

    @Value("${"executor.thread.count"}")
    private int executorThreadCount;

    @Bean("executorThreadPool")
    public ThreadPoolExecutor cachedThreadPool() {
        return new ThreadPoolExecutor(executorThreadCount, executorThreadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    }
}

应用部署在独立的 Tomcat 实例上。当Tomcat服务器关闭时,我发现队列中还有未完成的任务。结果,我会丢失数据。有没有办法让我在这个执行程序服务上调用 awaitTermination 以便它有机会完成队列中的内容?谢谢!

【问题讨论】:

  • 我确定有——但是现在如果 Tomcat 服务器或 Java 应用程序崩溃了怎么办?如果队列中的信息很重要,我会努力维护队列的持久性(不是一个词......但你知道我的意思吗?)——这样当 Java 应用程序重新启动时,它可以填充队列与未完成的项目。我知道这根本不能回答你的问题——对此我很抱歉!祝你的项目好运!
  • 谢谢@Andrew。你的问题是合法的。如果 - 上帝保佑 - 系统崩溃,这些任务是我可以承受的。但是,我想避免在正常关机期间丢失数据。

标签: java spring spring-boot executorservice shutdown


【解决方案1】:

使用@PreDestroy 注释进行注释。然后从那里执行执行服务的关闭。

@Configuration
class ExecutorServiceConfiguration {

    @Value("${"executor.thread.count"}")
    private int executorThreadCount;


     public static class MyExecutorService {
           private ThreadPoolExecutor executor;

           public MyExecutorService(ThreadPoolExecutor executor) {
               this.executor = executor;
           }
           @PreDestroy()
           public destroy() {
                  // destroy executor
           }
     }

    @Bean("executorThreadPool")
    public ThreadPoolExecutor cachedThreadPool() {
        return new ThreadPoolExecutor(executorThreadCount, executorThreadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    }

    @Bean
    public MyExecutorService configureDestroyableBean(ThreadPoolExecutor cachedThreadPool) 
    {
      return new MyExecutorService(cachedThreadPool);
    }

}

【讨论】:

  • 我考虑过这个选项。但是我怎样才能获得对 executor bean 的引用呢?
  • 更新了示例。当然,您将在现实世界中使用包装类。
【解决方案2】:

您可以通过配置 TomcatEmbeddedServletContainerFactory bean 来挂钩到 Tomcat 生命周期。它有一个方法 addContextLifecycleListeners 允许您实例化您自己的 LifecycleListener 并根据需要处理任何Tomcat Lifecycle Events(例如,通过在您的ExecutorService 上调用awaitTermination)。

@Configuration
public class TomcatConfiguration implements LifecycleListener {

    @Autowire("executorThreadPool")
    private ThreadPoolExecutor executor;

    @Bean
    public EmbeddedServletContainerFactory embeddedTomcatFactory() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
        factory.addContextLifecycleListeners(this);
        return factory;
    }

    @Override
    public void lifecycleEvent(LifeCycleEvent event) {
        //if check for correct event        
        executor.awaitTermination();
    }
}

【讨论】:

  • 非常感谢@nicholas。这是把它带到一个不同的层次。我从没想过以编程方式管理 Tomcat。希望在容器关闭挂钩中添加一些代码。但我正在工作。我一定会试试你的代码。谢谢!
  • 我能够让它工作。谢谢@nicholas!我今天学到了新东西!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-04
  • 2017-07-17
  • 1970-01-01
  • 2018-11-26
  • 1970-01-01
  • 2015-09-09
  • 2020-08-27
相关资源
最近更新 更多