我在spring bean中创建了一个threadpoolexecutor,所以当tomcat关闭时我需要关闭这个执行器。
public class PersistBO implements InitializingBean {
private ThreadPoolExecutor executer;
public void shutdownExecutor() {
executer.shutdown();
}
@Override
public void afterPropertiesSet() throws Exception {
taskQueue = new LinkedBlockingQueue<Runnable>(queueLength);
executer = new ThreadPoolExecutor(minThread, maxThread, threadKeepAliveTime,
TimeUnit.SECONDS, taskQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
}
我在google上搜索了解决方案并获得了结果。那就是为java.lang.runtime添加一个shutdownhook。但是,java文档说java.lang.Runtime#shutdownHook在最后一个非守护程序线程退出时被调用。所以这是一个死锁。在spring bean中有关闭执行程序的解决方案吗?
答案 0 :(得分:3)
我猜执行程序的生命周期应该取决于应用程序的生命周期,而不是整个Tomcat。
Runtime.shutdownHook()不适用。由于您已经使用Spring及其InitializingBean
进行初始化,因此可以在关闭应用程序上下文时使用DispasableBean
执行清理:
public class PersistBO implements InitializingBean, DisposableBean {
public void destroy() {
shutdownExecutor();
}
...
}
答案 1 :(得分:0)
使用Runtime
添加shutdown hook。这是Heinz Kabutz的一篇非常好的教程:http://www.roseindia.net/javatutorials/hooking%20_into_the_shutdown_call.shtml
答案 2 :(得分:0)
您可以实现自己的javax.servlet.ServletContextListener以在关闭应用程序时收到通知,并从侦听器关闭池。
答案 3 :(得分:0)
在bean的shutdown方法上使用@Predestroy注释。这将导致spring在关闭上下文时调用此方法
检查是否有某个执行程序服务在后台运行了一个线程。您可以通过调用executor.shutdownNow()
来关闭执行程序。
另见http://taranmeet.com/jvm-not-shutting-down-on-spring-context-close/
答案 4 :(得分:0)
以下是如何在Spring bean中启动和停止线程。
@PostConstruct
public void init() {
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("myspringbean-thread-%d").build();
executorService = Executors.newSingleThreadExecutor(factory);
executorService.execute(new Runnable() {
@Override
public void run() {
try {
// do something
System.out.println("thread started");
} catch (Exception e) {
logger.error("error: ", e);
}
}
});
executorService.shutdown();
}
@PreDestroy
public void beandestroy() {
if(executorService != null){
executorService.shutdownNow();
}
}