【问题标题】:ScheduledExecutorService and uncaught ErrorScheduledExecutorService 和未捕获的错误
【发布时间】:2014-12-03 22:17:53
【问题描述】:

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 行为,执行程序中的错误被“忽略”了吗?
  2. 处理这种情况的正确方法是什么?

【问题讨论】:

标签: java exception scheduledexecutorservice


【解决方案1】:

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

【讨论】:

  • 对,我现在已经尝试过了,而且(当然)你是对的,它确实如此。虽然您的答案是正确的,但这是一个丑陋的解决方案......真正的任务本身使用 try/catch 块进行常规异常处理,但不会捕获错误......此外,在主线程(或非Executor thread)不是很实用。如果我想阻止那里,我就不会使用延迟。这不是你的错,但你建议的解决方案是“丑陋的”。
猜你喜欢
  • 2012-12-12
  • 1970-01-01
  • 2017-03-26
  • 2017-06-14
  • 2011-02-24
  • 2014-09-28
  • 2021-06-23
  • 2015-09-20
  • 1970-01-01
相关资源
最近更新 更多