我使用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。
ContextClosedEvent
@Component public class ExecutorsStop implements ApplicationListener<ContextClosedEvent> { @Autowired ExecutorsStart executorsStart; @Override public void onApplicationEvent(final ContextClosedEvent event) { System.out.println("Stopped: " + event); } }
当Servlet容器关闭,它要求contextDestroyed(..)在它的各种ServletContextListener和destroy()它的Servlet实例。在ContextLoaderListener和DispatcherServlet每个呼叫close()他们ApplicationContext。
contextDestroyed(..)
ServletContextListener
destroy()
Servlet
ContextLoaderListener
DispatcherServlet
close()
ApplicationContext