我对Tomcat不太熟悉,在我看来它基本上被抽象为cgi服务器,可以在调用之间保存JVM - 我知道它可以做更多的事情。
我正在寻找一种在Tomcat服务器启动时启动后台线程的方法,它会定期更新服务器上下文(在我的特定情况下,这是一个侦听来自其他人的心跳的线程服务和更新可用性信息,但可以想象为此的各种用途)。
有没有标准的方法来做到这一点?启动和更新/查询Context?
非常感谢任何指向相关文档和/或代码示例的指示。
答案 0 :(得分:79)
如果要在部署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) {
}
}
}
答案 1 :(得分:12)
我正在寻找一种在Tomcat服务器启动时启动后台线程的方法
我认为您正在寻找一种在Tomcat启动您的Web应用程序时启动后台线程的方法。
这可以使用ServletContextListener来完成。它在web.xml中注册,并在您的应用程序启动或停止时调用。然后,您可以使用常规Java方法创建(并稍后停止)您的Thread,以创建一个Thread(或ExecutionService)。
答案 2 :(得分:5)
将<load-on-startup>1</load-on-startup>
放在web.xml中的<servlet>
块中会在Tomcat启动时立即强制执行servlet的init()
,而不是等待第一个请求到达。如果您想从init()
生成背景线程,这很有用。
答案 3 :(得分:2)
我只是对克里斯给出的非常详细的答案做了一点改动;我会将myThread
设置为myThread.setDaemon(true);
的守护程序线程,只要你有其他需要你的后台线程的非守护程序线程,它就会保持线程处于活动状态。当所有这些线程完成后,您的守护程序线程将被JVM停止,您无需在contextDestroyed
中自行处理它。
但那只是我的2美分。
答案 4 :(得分:2)
如果使用基于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();
}
}