Вы задаете два вопроса:
Вопрос 1. Является ли вызов System.exit() внутри метода destroy() сервлета для принудительного уничтожения любых потоков, не являющихся демонами, хорошей идеей?
Вызов System.exit() внутри ЛЮБОГО метода, связанного с сервлетом, всегда на 100% неверен. Ваш код — не единственный код, работающий в JVM — даже если вы — единственный работающий сервлет (в контейнере сервлета есть ресурсы, которые ему нужно будет очистить, когда JVM действительно выйдет).
Правильный способ справиться с этим случаем — очистить ваши потоки в методе destroy(). Это означает запускать их так, чтобы вы могли аккуратно остановить их правильным образом. Вот пример (где MyThread является одним из ваших потоков и расширяет ServletManagedThread):
public class MyServlet extends HttpServlet {
private List<ServletManagedThread> threads = new ArrayList<ServletManagedThread>();
// lots of irrelevant stuff left out for brevity
public void init() {
ServletManagedThread t = new MyThread();
threads.add(t);
t.start();
}
public void destroy() {
for(ServletManagedThread thread : threads) {
thread.stopExecuting();
}
}
}
public abstract class ServletManagedThread extends Thread {
private boolean keepGoing = true;
protected abstract void doSomeStuff();
protected abstract void probablySleepForABit();
protected abstract void cleanup();
public void stopExecuting() {
keepRunning = false;
}
public void run() {
while(keepGoing) {
doSomeStuff();
probablySleepForABit();
}
this.cleanup();
}
}
Также стоит отметить, что существуют библиотеки потоков/параллельности, которые могут помочь с этим, но если у вас действительно есть несколько потоков, которые запускаются при инициализации сервлета и должны работать до тех пор, пока сервлет не будет уничтожен, это, вероятно, все, что вам нужно. .
Вопрос 2. Почему Tomcat 5.0.30 и (более поздние версии, включая Tomcat 6.x.x) не завершают работу должным образом, если в методе destroy() сервлета есть System.exit()?
Без дополнительного анализа трудно сказать наверняка. Microsoft сообщает, что ошибка 1053 возникает, когда Windows запрашивает выключение службы, но время запроса истекает. Это могло бы создать впечатление, что что-то произошло внутри Tomcat, что привело его в очень плохое состояние. Я, конечно, подозреваю, что причиной может быть ваш звонок System.exit(
). Tomcat (в частности, Catalina) регистрирует хук выключения с виртуальной машиной (see org.apache.catalina.startup.Catalina.start()
, по крайней мере, в 5.0.30). Этот хук выключения будет вызываться JVM, когда вы вызываете System.exit()
. Перехватчик выключения делегирует работу запущенным службам, поэтому потенциально от каждой службы может потребоваться выполнение большого объема работы.
Если хуки выключения (triggered by your System.exit()
) не выполняются (они блокируются или что-то в этом роде), то очень легко понять, почему возникает ошибка 1053, учитывая документацию метода Runtime.exit(int)
(который вызывается из System.exit()
):
Если этот метод вызывается после того, как виртуальная машина начала свою последовательность выключения, то, если запущены перехватчики выключения, этот метод будет заблокирован на неопределенный срок. Если перехватчики выключения уже были запущены и включена финализация при выходе, то этот метод останавливает виртуальную машину с заданным кодом состояния, если состояние не равно нулю; в противном случае он блокируется на неопределенный срок.
Это поведение «бессрочной блокировки» определенно вызовет ошибку 1053.
Если вам нужен более полный ответ, вы можете загрузите исходный код и отладьте его самостоятельно.
Но я готов поспорить, что если вы правильно справитесь с проблемой управления потоками (как указано выше), ваши проблемы исчезнут.
Короче говоря, оставьте вызов System.exit() Tomcat — это не ваша работа.
person
Jared
schedule
13.02.2009