如何在tomcat关闭时关闭spring bean中的ThreadPoolExecutor?

时间:2012-01-31 08:27:20

标签: java spring javabeans shutdown

我在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中有关闭执行程序的解决方案吗?

5 个答案:

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