Как правильно отключать потоки при закрытии tomcat? - PullRequest
4 голосов
/ 29 марта 2012

Я пытаюсь завершить работу потоков, когда Tomcat завершает работу.
В частности, я пытаюсь завершить работу log4j watchdog (для обмена файлами), а также пытаюсь завершить работу исполнителя, использующего класс в моем веб-приложении.
При завершении работы я вижу исключения в Catalina.out.
Для Log4J я вижу:

ИНФОРМАЦИЯ: Неверный доступ: этот экземпляр веб-приложения уже остановлен
.Не удалось загрузить org.apache.log4j.helpers.NullEnumeration.
Возможная следующая трассировка стека вызвана ошибкой, выданной для
целей отладки, а также для попытки завершить поток, который
вызвал недопустимый доступи не имеет функционального влияния.Произошло сбрасывание
: java.lang.IllegalStateException
в org.apache.catalina.loader.WebappClassLoader.loadClass (WebappClassLoader.java:1587)
в org.apache.catalina.loader.WebappClassLoader.load.java: 1546)
в org.apache.log4j.Category.getAllAppenders (Category.java:413)
в org.apache.log4j.Category.closeNestedAppenders (Category.java:226)
в организации.apache.log4j.Hierarchy.shutdown (Hierarchy.java:467)
в org.apache.log4j.LogManager.shutdown (LogManager.java:267)
в com.listeners.myListener $ 1.run (myListener.java: 232)
Исключение в потоке "Thread-14" java.lang.NoClassDefFoundError:
org.apache.log4j.helpers.NullEnumeration
в org.apache.log4j.Category.getAllAppenders (Category.java: 413)
в org.apache.log4j.Category.closeNestedAppenders (Category.java:226)
в org.apache.log4j.Hierarchy.shutdown (Hierarchy.java:467)
в org.apache.log4j.LogManager.shutdown (LogManager.java:267)

идля части исполнителя:

ИНФОРМАЦИЯ: Нелегальный доступ: этот экземпляр веб-приложения уже остановлен
.Не удалось загрузить com.my.class.SomeClass.Возможная
следующая трассировка стека вызвана ошибкой, генерируемой для отладки
целей, а также для попытки завершить поток, который вызвал
несанкционированный доступ, и не оказывает никакого функционального влияния.Возникло сбрасывание:
java.lang.IllegalStateException
в org.apache.catalina.loader.WebappClassLoader.loadClass (WebappClassLoader.java:1587)
в org.apache.catalina.loader.WebappClassLoader.load.java: 1546)
в Исключении в потоке "Thread-13" java.lang.NoClassDefFoundError:
com.my.class.SomeClass

То, что я делаю, находится в ServletContextListener на contextDestroyed Я добавил отключающие перехватчики следующим образом:

public void contextDestroyed(ServletContextEvent arg0) {  

         Runtime.getRuntime().addShutdownHook(new Thread(){  
            @Override  
            public void run(){  
                LogManager.shutdown();                  
            }  
         });  

    } 





 public void contextDestroyed(ServletContextEvent arg0) {  

        Runtime.getRuntime().addShutdownHook(new Thread(){  
            @Override  
            public void run(){  
                SomeClass.updater.shutdown();  
            }  
        });  

    }  

Что я здесь не так делаю?Почему я получаю исключения?

ОБНОВЛЕНИЕ:
SomeClass.updater является public static ScheduledExecutorService.
LogManager является org.apache.log4j.LogManager

ОБНОВЛЕНИЕ2:
После получения ответа от BGR я делаю напрямую

public void contextDestroyed(ServletContextEvent arg0) {  

            SomeClass.updater.shutdown();  

        }  

и

public void contextDestroyed(ServletContextEvent arg0) {  

                LogManager.shutdown();                  

        } 

Я не получаю исключения из Log4j, но получаю следующее исключение для SomeClass.updater, котороеpublic static ScheduledExecutorService:

ИНФОРМАЦИЯ: Нелегальный доступ: этот экземпляр веб-приложения уже остановлен
.Не удалось загрузить java.util.concurrent.ExecutorService.Возможная следующая трассировка стека
вызвана ошибкой, выдаваемой для отладки
, а также для попытки завершить поток, который
вызвал несанкционированный доступ и не имеет функционального влияния.Возникла ошибка
: java.lang.IllegalStateException
в org.apache.catalina.loader.WebappClassLoader.loadClass (WebappClassLoader.java:1587)
в org.apache.catalina.loader.WebappClassLoader.load.java: 1546)

Почему?Уроки уже были собраны мусором?

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

Я бы регистрировал перехватчики завершения в методе init () сервлета, а не contextDetroyed (), но в любом случае, зачем вам перехватчики отключения во-первых?

Разве вы не можете просто вызвать SomeClass.updater.shutdown(); напрямую в методе contextDestroyed ()?

EDIT

contextDestroyed() слушателя опоздал на службу исполнителя. Как указано в javadoc Все сервлеты и фильтры будут уничтожены до Все ServletContextListeners уведомляются о разрушении контекста.

, тогда как переопределение сервлета destroy() должно быть в порядке, как в javadoc . Этот метод дает сервлету возможность очищать любые ресурсы, которые хранятся (например, память, файловые дескрипторы, * нити 1023 * ...

@Override
public void destroy(  ) {


        myThreadExecutor.shutdown();

        super.destroy(  );
}
2 голосов
/ 08 августа 2012

Вызов

LogManager.shutdown();

в методе contextDestroyed () является первым шагом, но ExecutorService закрывается не сразу.Вы получаете исключения, потому что потоки ExecutorService все еще работают после возврата метода contextDestroyed ().Вам нужно сделать:

public void contextDestroyed(ServletContextEvent arg0) {  
    LogManager.shutdown();
    if(LogManager.awaitTermination(10, TimeUnit.SECONDS) == false) {
        LogManager.shutdownNow();
    }
} 

Таким образом, пул потоков закрылся и остановил все потоки при выходе из contextDestroyed ().

...