【问题标题】:How to shutdown ThreadPoolExecutor in spring bean when tomcat is shutdown?当tomcat关闭时如何关闭spring bean中的ThreadPoolExecutor?
【发布时间】:2012-01-31 08:27:20
【问题描述】:

我在一个spring bean中创建了一个threadpoolexecutor,所以我需要在tomcat关闭时关闭这个executor。

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

我在谷歌上搜索了解决方案并得到了结果。也就是给java.lang.runtime加一个shutdownhook。但是,java 文档说 java.lang.Runtime#shutdownHook 在最后一个非守护线程退出时被调用。所以这是一个死锁。 spring bean中关闭执行器有什么解决方案吗?

【问题讨论】:

  • 如果您提供正确的线程工厂,您的池也可以使用守护线程。

标签: java spring javabeans shutdown


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    使用Runtime 添加shutdown hook。这是 Heinz Kabutz 的一个非常好的教程:http://www.roseindia.net/javatutorials/hooking%20_into_the_shutdown_call.shtml

    【讨论】:

    • 但是 java 文档说 java.lang.Runtime#shutdownHook 在最后一个非守护线程退出时被调用。会不会是死锁?
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

      另见http://taranmeet.com/jvm-not-shutting-down-on-spring-context-close/

      【讨论】:

        【解决方案5】:

        这里是如何在 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();
          }
         }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-26
          • 2011-07-06
          • 2014-11-17
          • 2013-12-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多