在Code Review chat中的讨论确定了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行为吗,Executors中的错误会被“忽略”吗?
- 如何正确处理这种情况?