Java 当tomcat关闭时,如何关闭Springbean中的ThreadPoolExecutor?

Java 当tomcat关闭时,如何关闭Springbean中的ThreadPoolExecutor?,java,spring,javabeans,shutdown,Java,Spring,Javabeans,Shutdown,我在Springbean中创建了一个threadpoolexecutor,所以我需要在tomcat关闭时关闭这个执行器 public class PersistBO implements InitializingBean { private ThreadPoolExecutor executer; public void shutdownExecutor() { executer.shutdown(); } @Override public void afterPrope

我在Springbean中创建了一个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());
}
public类PersistBO实现初始化bean{
私有线程池执行器;
公共无效关闭执行器(){
executer.shutdown();
}
@凌驾
public void afterPropertieSet()引发异常{
taskQueue=新的LinkedBlockingQueue(queueLength);
executer=新的线程池执行器(minThread、maxThread、threadKeepAliveTime、,
TimeUnit.SECONDS,taskQueue,new ThreadPoolExecutor.DiscardOldestPolicy();
}

我在google上搜索了解决方案并得到了一个结果。那就是在java.lang.runtime中添加一个shutdownhook。但是,java文档说java.lang.runtime#shutdownhook是在最后一个非守护进程线程退出时调用的。所以它是一个死锁。SpringBean中有没有关闭executor的解决方案?

使用
运行时
添加一个Heinz Kabutz的e是一个非常好的教程:

我想执行器的生命周期应该取决于应用程序的生命周期,而不是整个Tomcat。您可以在Tomcat仍在运行时停止应用程序,因此
Runtime.shutdownHook()
不适用

由于您已经使用Spring及其
InitializingBean
进行初始化,因此可以在关闭应用程序上下文时使用它执行清理:

public class PersistBO implements InitializingBean, DisposableBean { 
    public void destroy() {
        shutdownExecutor();
    }
    ...
}

您可以实现自己的,以便在应用程序关闭时收到通知,并从侦听器关闭池。

在bean上的关闭方法上使用@Predestroy注释。这将导致spring在上下文关闭时调用此方法

检查是否有某个执行器服务在后台运行线程。您可以通过调用
executor.shutdownNow()
关闭执行器


另请参见

这里是如何在Springbean中启动和停止线程

    @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();
  }
 }

但是java文档说,当最后一个非守护进程线程退出时,会调用java.lang.Runtime#shutdownHook。这会是死锁吗?如果您为池提供了正确的线程工厂,那么它也可以使用deamon线程。