2

考虑我使用 ScheduledExecutorService 为定期执行安排了一个 Runnable,并且发生了一些系统错误,例如 OutOfMemory。它会被无声地吞噬。

scheduler.scheduleWithFixedDelay(new Runnable() {
                    @Override
                    public void run() {
                      throw new OutOfMemoryError(); // Swallowed
                    }
                }, 0, delay, TimeUnit.SECONDS);

正常吗?

为什么它不传播到容器?

处理此类错误的正确方法是什么?

谢谢!

4

5 回答 5

2

与的OutOfMemoryError任何子类型一样Error,无法从中恢复,它们通常对您的程序是致命的。无论您是否尝试捕捉它并不重要,您的程序正在下降。

但是,如果您的意思是 anException而不是 an Error,那么您有 2 个选项:

  1. 从任务的run()方法中捕获异常。
  2. 调用返回get()的. 这会将异常传播回提交线程,但它会阻塞直到发生这种情况。Future()scheduleWithFixedDelay()
于 2011-01-12T22:59:45.143 回答
1

该方法将返回一个 ScheduledFuture 实例,它的 get 方法(有或没有超时)将抛出一个 ExecutionException 并以您的 OutOfMemoryError 作为原因。

于 2011-01-12T22:52:37.090 回答
0

guavaListenableFuture类在这里可能很有用。

有了这个,您可以创建一个异常处理程序任务来记录错误,然后尝试重新启动失败的任务。

您仍然需要一个休眠线程来监视异常,但您只需要一个用于整个进程的全局异常处理程序线程(而不是每个计划任务一个。)

于 2011-01-12T23:06:05.180 回答
0

就我个人而言,我会给你的对象一种报告异常的机制,而不是期望一个框架来处理它们。想想一个异常监听器或类似的东西。

对于 oom,您无能为力。

这些执行者在那里吃饭是为了执行你的东西,而不是处理你的代码可能存在的所有问题!

于 2011-01-13T01:48:37.913 回答
0

您可以使用jcabi-logVerboseRunnable中的类,它会捕获所有异常并记录它们:

import com.jcabi.log.VerboseRunnable;
Runnable runnable = new VerboseRunnable(
  Runnable() {
    public void run() { 
      // do business logic, may Exception occurs
    }
  },
  true // it means that all exceptions will be swallowed and logged
);

现在,当有人调用时,runnable.run()不会抛出异常。相反,它们被吞下并记录(到 SLF4J)。

于 2013-04-06T05:37:53.830 回答