5

后端 web 应用程序部署在 Tomcat 6 servlet 容器上。在 webapp 中,启动了几个监控线程。问题在于关机。

  • 我怎么知道 webapp 被请求关闭?
  • 我应该如何在我的线程中处理这个?

目前我的线程实现如下。当 servlet 被指示关闭 (shutdown.sh) 时,它确实完成了干净的关闭并且不会因为这个线程而挂起——为什么?

class Updater extends Thread {
  volatile boolean interrupted = false;

  @Override
  public void run() {
    Integer lastUpdateLogId = CommonBeanFactory.getXXX()
                              .getLastUpdateLogRecordKey(MLConstants.SMART_DB_NAME);

    List<UpdateLog> updateLogRecords;
    while (!interrupted) {
      boolean isConfigurationUpdateRequested = false;

      try {
        TimeUnit.SECONDS.sleep(5);
      } catch (InterruptedException e) {
        setInterrupted(true);
      }

      updateLogRecords = CommonBeanFactory.getXXX()
                         .getLastFactsUpdateLogRecords(MLConstants.XXXX, lastUpdateLogId);

      for(UpdateLog updateLog : updateLogRecords) {
        if (updateLog.getTable_name().equals(MLConstants.CONFIG_RELOAD)) {
          isConfigurationUpdateRequested = true;
        }

        lastUpdateLogId = updateLog.getObjectKey();
      }

      if (isConfigurationUpdateRequested) {
        Configuration.getInstance().loadConfiguration();
      }
    }
  }

  public boolean getInterrupted() {
    return interrupted;
  }

  public void setInterrupted(boolean interrupted) {
    this.interrupted = interrupted;
  }
}
4

2 回答 2

6

我想我还不能回复答案。埃迪的回答并不完全正确。

我发现了这个问题,因为我想弄清楚为什么我的 webapp 没有正确关闭;当我运行关机时,我的线程不会被杀死。*。事实上,它会停止一些线程,但最终只是处于某种不确定状态。事实上,我的课几乎和这个一模一样。

在前台 Tomcat 窗口(在 Windows 上)中键入 Ctrl+C 会停止一切,但是使用 Tomcat 附带的 init 脚本不会。不幸的是,我还没有弄清楚为什么......

编辑:我想通了。我的大多数监视线程都是在 ServletContextListener 中启动的,但是当该上下文被“破坏”时,子线程不会得到通知。我通过简单地将所有子线程保存在 List 中并循环遍历,在 contextDestroyed() 方法中对每个子线程调用 Thread.interrupt() 来修复它。这与 Eddie 所说的 servlet destroy() 方法几乎相同。

但是,当您运行 shutdown.{sh|bat} 时,JVM 立即关闭是不正确的。这更像是该脚本向 Tomcat 组件发送关闭请求。您可以接收这些关闭消息并将它们传递给您自己的对象。

于 2011-03-23T13:48:15.540 回答
3

Servlet 在被指示关闭时会收到生命周期事件。您可以使用此事件来停止您的监控线程。也就是说,当一个 servlet 启动时,它的init()方法被调用。当它停止时,它的destroy()方法被调用。

覆盖destroy()servlet 中的方法并在那里停止线程。

当你调用shutdown.sh整个 JVM 时就关闭了。由于 JVM 停止,所有线程(无论其状态如何)如果仍在运行,将被强制停止。这是调用的逻辑等价物System.exit(0);

于 2009-03-17T20:33:40.390 回答