Подтвердить что ты не робот

ScheduledExecutorService и непроверенная ошибка

Обсуждение в чате обзора кода определило следующее поведение из ScheduledExecutorService:

Запланированная задача не работает с серьезной проблемой, но нет отчета, исключения или журнала проблемы. В других контекстах приложение обычно заканчивается ошибкой. В контексте ScheduledExecutorService, однако, вообще нет обработки "Исключение/ошибка".

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

public class InitializerFault {

    private static final int value = Integer.parseInt("fubar");

    @Override
    public String toString() {
        return "" + value;
    }

}

При запуске как:

public static void main(String[] args) {
    System.out.println(new InitializerFault());
}

он производит (именно это я и ожидал):

Exception in thread "main" java.lang.ExceptionInInitializerError
    at SimpleHandler.main(SimpleHandler.java:5)
Caused by: java.lang.NumberFormatException: For input string: "fubar"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:580)
    at java.lang.Integer.parseInt(Integer.java:615)
    at InitializerFault.<clinit>(InitializerFault.java:4)
    ... 1 more

Но при запуске как:

private static final Thread buildThread(Runnable r) {
    Thread t = new Thread(r, "TestThread");
    t.setDaemon(true);
    System.out.println("Built thread " + t);
    return t;
}
public static void main(String[] args) throws InterruptedException {
    // use a thread factory to create daemon threads ... can be non-daemon as well.
    ScheduledExecutorService ses = Executors.newScheduledThreadPool(
           2, (r) -> buildThread(r));
    ses.scheduleAtFixedRate(
           () -> {System.out.println(new InitializerFault());},
           500, 1000, TimeUnit.MILLISECONDS);
    Thread.sleep(3000);
    System.out.println("Exiting");
}

он производит только:

Built thread Thread[TestThread,5,main]
Exiting

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

Два вопроса:

  • - это ожидаемое поведение Java, что ошибки в исполнителя игнорируются?
  • Какой правильный способ справиться с этой ситуацией?
4b9b3361

Ответ 1

ScheduledExecutorService.scheduleAtFixedRate возвращает a ScheduledFuture. Если мы будем называть ScheduledFuture.get(), поток будет блокировать и ждать завершения периодической задачи, что может произойти после отмены задачи или если задача выдает исключение. В последнем случае get() будет бросать java.util.concurrent.ExecutionException с завернутым оригинальным исключением