Ловит Java Throwable лучший способ перезапустить поток - PullRequest
0 голосов
/ 22 мая 2018

У меня следующий код в java-

@Override
public void run() {

    logger.info("Thread Started:" + this.getName());

    try {
        runJob();
    } catch( Throwable e) {
        logger.error("Exception in running thread: " + this.getName() + ", restarting job", e);
        run();
    }
}

public void runJob() {

    while(true) {
       try {
           // Work here
       } catch(Exception e) {
           // log the exception
       }
    }
 }

Будет ли этот код поддерживать поток в каждом случае, и это единственный способ восстановить поток?

Этоэто альтернатива, о которой я подумал после прочтения всех ответов.Дайте мне знать, если это хороший способ сохранить поток живым навсегда, даже если произошла ошибка:

@Override
public void run() {

    logger.info("Thread Started:" + this.getName());

    while(true) {
      try {
        runJob();
      } catch( Throwable e) {
        logger.error("Exception in running thread: " + this.getName() + ", restarting job", e);
        }
    }
}

public void runJob() {

     try {
          // Work here
     } catch(Exception e) {
          // log the exception
     }
 }

Ответы [ 3 ]

0 голосов
/ 22 мая 2018

Он не «восстановит» его, а скорее начнет заново и попытается снова.Это может привести к бесконечному циклу рекурсивных вызовов, пока не произойдет StackOverflow.И в этом случае ваше приложение будет остановлено в любом случае.

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

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

0 голосов
/ 22 мая 2018

Это имеет мало общего с "потоками".Логика повторных попыток может быть реализована для исключений, и это обычная практика.

Тем не менее, перехват Throwable явно опасен.Вы хотели бы повторить попытку при ошибках выбора (таких как тайм-аут, сбой соединения и т. Д.), Что, конечно, требует более точных знаний о том, как работает ваш метод runJob().

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

boolean retry = false;
do {
    try {
        runJob();
        retry = false;
    } catch (SpecificException e) { //timeout, network failure exceptions
        logger.error("Exception in running thread: "
            + this.getName() + ", restarting job");
        retry = true;
    }
} while(retry);

Вам также может понадобиться добавить счетчик, чтобы ограничить количество повторных попыток.

0 голосов
/ 22 мая 2018

Вы никогда не должны контролировать поток с помощью try-catch!

Более того, если вы вызовете этот неудачный метод в catch, он будет вызван снова, вызывая рекурсивный бесконечный цикл, поэтому StackOverflowError.

Я предлагаюВы создаете счетчик, чтобы ограничить максимальное количество попыток.Для этого варианта использования вдохновитесь вопросом Как реализовать повторную попытку?

Существует множество библиотек, предлагающих механизм восстановления.Я рекомендую вам jcabi-aspects.

...