ScheduledExecutorService和未捕获错误

13
Code Review chat中的讨论确定了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引发了一个复杂的实际调试过程,问题很难被隔离。

两个问题:

  1. 这是预期的Java行为吗,Executors中的错误会被“忽略”吗?
  2. 如何正确处理这种情况?

这可以帮助你线程池中的异常处理 - Tkachuk_Evgen
1个回答

4

ScheduledExecutorService.scheduleAtFixedRate会返回一个ScheduledFuture。如果我们调用ScheduledFuture.get(),线程将会阻塞并等待周期性任务的完成,这可能会在任务取消或任务抛出异常时发生。在后一种情况下,get()将抛出java.util.concurrent.ExecutionException,其中包含原始异常。


4
好的,我已经尝试过了,(当然)你是正确的,它起作用了。虽然你的答案是正确的,但是这是一个不太好的解决方案... 实际任务本身使用try/catch块进行常规异常处理,但不捕获错误... 另外,在主线程上“等待”(或非Executor线程)并不实用。如果我想要在那里阻塞,我就不会使用延迟。这不是你的错,但你提出的解决方案是“丑陋”的。 - rolfl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接