Вы задаете два вопроса:
Вопрос 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.xx) не удается правильно завершить работу, если в методе 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 - это не ваша работа.