Фоновый поток для приложения сервлета Tomcat

Я не очень знаком с Tomcat, в моей голове он в основном абстрагируется как cgi-сервер, который сохраняет JVM между вызовами - хотя я знаю, что он может намного больше.

Я ищу способ запустить фоновый поток при запуске сервера Tomcat, который будет периодически обновлять контекст сервера (в моем конкретном случае это поток, который прослушивает биения некоторых других служб и обновляет информацию о доступности, но можно представить себе множество вариантов использования для этого).

Есть стандартный способ сделать это? И запуск, и обновление / запрос контекста?

Мы будем очень благодарны за любые указатели на соответствующую документацию и / или образцы кода.


person SquareCog    schedule 27.04.2009    source источник
comment
Стоит отметить, что обычно вы можете просто запустить поток, когда захотите, если для этого есть более удобное место, чем при инициализации контекста. Например. это может быть метод инициализации конкретного сервлета, или когда конкретный класс запускается впервые и т. д.   -  person Neil Coffey    schedule 27.04.2009


Ответы (5)


Если вы хотите запустить поток при развертывании WAR, вы можете определить прослушиватель контекста в файле web.xml:

<web-app>
    <listener>
       <listener-class>com.mypackage.MyServletContextListener</listener-class>
    </listener>
</web-app>

Затем реализуйте этот класс примерно так:

public class MyServletContextListener implements ServletContextListener {

    private MyThreadClass myThread = null;

    public void contextInitialized(ServletContextEvent sce) {
        if ((myThread == null) || (!myThread.isAlive())) {
            myThread = new MyThreadClass();
            myThread.start();
        }
    }

    public void contextDestroyed(ServletContextEvent sce){
        try {
            myThread.doShutdown();
            myThread.interrupt();
        } catch (Exception ex) {
        }
    }
}
person Chris Thornhill    schedule 27.04.2009
comment
Ах! Спасибо, это очень просто. Правильно ли я говорю, что ServletContext - это то, что мне нужно изменить, чтобы этот поток передавал информацию моему сервлету, чтобы он мог использовать статусы, которые собирает мой слушатель сердцебиения? - person SquareCog; 27.04.2009
comment
Да, пропустил эту часть в своем ответе. :) ServletConext доступен из ServletContextEvent, который может быть передан в ваш объект Thread, который может получать / устанавливать атрибуты, доступные для всех потоков. - person Chris Thornhill; 27.04.2009
comment
На этом этапе, как можно получить доступ к MyServletContextListener для запроса потока? - person Daniele Orlando; 23.11.2016

Я ищу способ запустить фоновый поток при запуске сервера Tomcat

Я думаю, вы ищете способ запустить фоновый поток, когда ваше веб-приложение запускается Tomcat.

Это можно сделать с помощью ServletContextListener. . Он зарегистрирован в web.xml и будет вызываться при запуске или остановке вашего приложения. Затем вы можете создать (а позже остановить) свой поток, используя обычные способы Java для создания потока (или ExecutionService).

person Thilo    schedule 27.04.2009

Помещение <load-on-startup>1</load-on-startup> в блок <servlet> в вашем web.xml заставит init() вашего сервлета произойти сразу после запуска Tomcat, а не ждать прибытия первого запроса. Это полезно, если вы хотите создать фоновый поток из init().

person divbyzero    schedule 17.03.2012
comment
Это помогло мне, настолько простое по сравнению с другими решениями здесь, но настолько без рейтинга и хорошо подходящим для запуска некоторых фоновых приложений или демонов. Спасибо! - person Arturas M; 09.04.2016

Я просто немного изменил бы очень подробный ответ, который дал Крис; Я бы установил myThread как поток Daemon от myThread.setDaemon(true);, который в основном будет поддерживать поток активным, пока у вас работают другие потоки, отличные от Daemon, которым нужен ваш фоновый поток. Когда все эти потоки завершаются, ваш поток Daemon останавливается JVM, и вам не нужно обрабатывать его самостоятельно в contextDestroyed. Но это всего лишь мои 2 цента.

person Ittai    schedule 24.09.2009
comment
За исключением того, что вам все еще нужно обрабатывать это в contextDestroyed. Демоны завершаются, когда завершается последний недемонический поток, а не когда завершается контекст сервлета. Если вы развернете файл WAR для замены того, который в настоящее время запущен, поток демона из старого контекста сервлета будет продолжать работу. Это, в свою очередь, удерживает ClassLoader этого контекста, что является утечкой памяти PermGen, что плохо. - person David Leppik; 18.01.2013

Другой способ, если вы используете фреймворк на основе Spring, вы можете указать класс / поток, который вы хотите инициализировать, в beans.xml. Поэтому при запуске tomcat beans.xml инициализирует все упомянутые в нем классы. При необходимости вы также можете передать аргументы конструктора. Ниже приведен пример того же.

beans.xml

<bean id="monitoringSvc" class="com.mypackage.MonitoringService">
    <constructor-arg value="60"></constructor-arg>
</bean>

MonitoringService.java

public class MonitoringService{

     private MyThread myThread;

     public MonitoringService(int seconds){
          myThread = new MyThread(seconds);
          myThread.start();
     }
}    
person Akshay    schedule 04.12.2014