addShutdownHook и setUncaughtExceptionHandler не работают должным образом в Java - PullRequest
3 голосов
/ 26 февраля 2010

У меня есть многопоточная программа, где у меня есть один поток для просмотра нескольких потоков. Функционирование устроено так:

Основная программа выполняет инициацию и запускает Watcher Thread, в void Main (), у меня есть строка

Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownThread(), "Exit Listener"));

Когда я не запускаю поток наблюдателя, при завершении работы программы вызывается ShutdownThread, но когда я запускаю поток наблюдателя, в котором есть мертвая петля, ShutdownThread не вызывается ( Я распечатаю сообщение в этой теме). Это очень, очень странно. Есть объяснения?

Нить наблюдателя имеет вид:

public void run(){
   boolean running=false;
   thread a=new thread(...); //Do the same thing for b, c, d...
   while(true){
   if (a.isActive()){
     if (running)
        thread a= new thread(...);
     a.start();
     running=true;
   }
   Thread.sleep(1000); //try catch block...
}

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

Как насчет использования сигналов? Есть ли хороший кроссплатформенный код для этого?

Тогда setUncaughtExceptionHandler тоже не работает. Я провел тестирование и обнаружил, что обработчик вообще не вызывается. Я не знаю почему. Код для обработчика:

    public static class ErrHandler implements Thread.UncaughtExceptionHandler{
    public final void uncaughtException(Thread t, Throwable e) {
            Error(t + "died, threw exception: " + e);
        }
    }//this is in public class globals

Я ловлю его, используя

producer.setUncaughtExceptionHandler(Globals.errhandler);

есть в моем коде, а я вижу только оригинальный e.printStack () вместо . Кажется, я не могу переопределить это ни в родительском потоке, ни в себе. Это так расстраивает. Я думаю поставить запись в очередь и почитать ее где-нибудь еще. По крайней мере, это может сработать.

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

1 Ответ

0 голосов
/ 26 февраля 2010

Не знаю, поможет ли это вам, но мы столкнулись с тем же поведением. Не все исключения правильно передаются зарегистрированному ExceptionHandler.

Интересно, существуют ли юнит-тесты для параллельной среды? Потому что это должно было быть обнаружено.

Мы реализовали ScheduledExecutorService сами, используя экземпляр ScheduledExecutorService в качестве делегата и инкапсулируя параметр Runnable / Callable каждого метода в реализации Runnable / Callable, которая исправляет поведение.

...