Как правильно уничтожить локальные потоки, принадлежащие веб-приложению, запущенному на tomcat, которое было приказано завершить работу - PullRequest
5 голосов
/ 17 марта 2009

Внутреннее веб-приложение развернуто в контейнере сервлета Tomcat 6. В веб-приложении запущено несколько потоков мониторинга. Проблема с выключением.

  • Как узнать, что веб-приложение запрашивается для завершения работы?
  • Как мне справиться с этим в моих темах?

В настоящее время моя тема реализована, как показано ниже. Когда сервлет получает команду на завершение работы (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;
  }
}

Ответы [ 2 ]

6 голосов
/ 23 марта 2011

Наверное, я пока не могу ответить на ответы. Ответ Эдди не совсем правильный.

Я нашел этот вопрос, потому что я пытаюсь выяснить, почему мое веб-приложение не закрывается должным образом; У меня есть темы, которые не убиваются при запуске shutdown. *. Фактически, он останавливает некоторые потоки, но в конечном итоге просто сидит в каком-то подвешенном состоянии. Мой класс почти такой же, как этот.

Ввод Ctrl + C в окне Tomcat на переднем плане (в Windows) останавливает все, однако использование сценария инициализации, поставляемого с Tomcat, этого не делает. К сожалению, я еще не понял, почему ...

Редактировать: Я понял это. Большинство моих потоков мониторинга запускаются в ServletContextListener, но когда этот контекст был «уничтожен», дочерние потоки не были уведомлены. Я исправил это, просто сохраняя все дочерние потоки в списке и просматривая их, вызывая Thread.interrupt () для каждого в методе contextDestroyed (). Это почти то же самое, что сказал Эдди о методе destroy () сервлета.

Однако неправильно, что JVM отключается при запуске shutdown. {Sh | bat}. Это больше похоже на то, что этот скрипт отправляет запрос на отключение компонентам Tomcat. Вам решать получать эти сообщения о завершении работы и передавать их вашим собственным объектам.

3 голосов
/ 17 марта 2009

Сервлеты получают событие жизненного цикла при получении инструкции на отключение. Вы можете использовать это событие, чтобы остановить поток мониторинга. То есть при запуске сервлета вызывается его метод init(). Когда он остановлен, вызывается его метод destroy().

Переопределите метод destroy() в вашем сервлете и остановите там нить.

Когда вы звоните shutdown.sh, вся JVM отключается. Поскольку JVM останавливается, все потоки (независимо от их состояния) принудительно останавливаются, если все еще работают. Это логический эквивалент вызова System.exit(0);

...