java – Spring webapp – 在应用程序停止时关闭线程

我使用Spring的ApplicationListener接口实例化ScheduledExecutorService,如下所示:

@Component
public class ExecutorsStart implements ApplicationListener<ContextRefreshedEvent> {

    private ScheduledExecutorService executor;

@Autowired
Scheduler scheduler;

@Override
public void onApplicationEvent(final ContextRefreshedEvent event) {
    executor = Executors.newSingleThreadScheduledExecutor();
    scheduler.init();
    int delay = 10;
    int period = 60;// repeat every 1 minutes.
    executor.scheduleAtFixedRate(scheduler, delay, period, TimeUnit.SECONDS);
}

目前,当我运行./shutdown.sh时,Tomcat不会干净地关闭,并带有消息:

The web application [/foo] appears to have started a thread named [pool-1-thread-1] but has failed to stop it

这似乎是因为我还没有编写代码来停止ScheduledExecutorService.

我的问题是:在这种环境下如何正确地完成这项工作?

我注意到存在一个ContextStoppedEvent,所以,我为它实现了一个监听器:

@Component
public class ExecutorsStop implements ApplicationListener<ContextStoppedEvent> {

@Autowired
ExecutorsStart executorsStart;

@Override
public void onApplicationEvent(final ContextStoppedEvent event) {
    executorsStart.executor.shutdownNow();
}

但是当Tomcat关闭时,似乎没有调用此事件处理程序.

我是否错误地实现了这个,或者我是否完全采用了这种方式?

最佳答案
您正在寻找ContextClosedEvent.

@Component
public class ExecutorsStop implements ApplicationListener<ContextClosedEvent> {

    @Autowired
    ExecutorsStart executorsStart;

    @Override
    public void onApplicationEvent(final ContextClosedEvent event) {
        System.out.println("Stopped: " + event);
    }
}

当Servlet容器关闭时,它会在其各种ServletContextListener上调用contextDestroyed(..)并在其Servlet实例上调用destroy(). ContextLoaderListener和DispatcherServlet分别在其ApplicationContext上调用close().

转载注明原文:java – Spring webapp – 在应用程序停止时关闭线程 - 代码日志