Исключение в runnable, кажется, убивает пул потоков - PullRequest
0 голосов
/ 16 января 2020

У меня есть runnable, который я хочу запускать периодически. Я полагаю, что при конкретном запуске runnable обнаружил нулевой указатель, но на консоли не было исключений. После этого неудачного запуска он никогда не запускается снова. У меня есть два вопроса:

  1. Если был нулевой указатель, почему это не было показано на консоли
  2. Как я могу запустить запланированное задание в будущем, даже если конкретный прогон не удался?
scheduler = Executors.newScheduledThreadPool(1);
MyRunnable mr = new MyRunnable(this.data);
scheduler.scheduleWithFixedDelay(mr, 0, STATUS_SENDER_PERIOD, TimeUnit.MILLISECONDS);

1 Ответ

0 голосов
/ 16 января 2020

Отвечая на ваши вопросы,

1) Причина, по которой вы не видите каких-либо исключений, заключается в том, что FutureTask#setException, вызываемый в FutureTask#run, эффективно поглощает его. Чтобы иметь возможность регистрировать исключение, вы должны либо создать новый класс, расширяющий ScheduledThreadPoolExecutor, и переопределить метод afterExecute следующим образом:

@Override
protected void afterExecute(Runnable r, Throwable t) {
    if (t == null && r instanceof Future<?>) {
        try {
            Object result = ((Future<?>) r).get();
         } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
         } catch (ExecutionException e) {
            t = e;
         }
    }

    if (t != null) {
        t.printStackTrace();
    }
}

или напрямую вызвать get в вернул ScheduledFuture примерно так:

var executor = Executors.newSingleThreadScheduledExecutor();
var future = executor.scheduleAtFixedRate(new MyRunnable(null), 1, 1, TimeUnit.SECONDS);

try {
    future.get();

} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

2) Самый простой способ перезапустить сбойный runnable - это сделать:

while (true) {
    try {
        future.get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
     }
}

Но imho этот подход не самый чистый , Правильное кодирование вашего Runnable#run метода для обработки исключений было бы лучшим решением.

...