前几天我在我的应用程序中实现了一项重要服务,无论如何都应该继续运行。所以我使用了以下结构:
ScheduledExecutorService ses =
Executors.newSingleThreadScheduledExecutor();
//If the thread dies, another will take over
ses.scheduleAtFixedRate(importantPeriodicTask, 1, 1, TimeUnit.NANOSECONDS);
...只是发现当importantPeriodicTask实际上抛出RuntimeException或Error时,ScheduledExecutorService
将停止执行此任务(它们将不再被安排)。
这当然是javadoc所说的:
如果执行了任务 遇到异常,随后 执行被压制。
对我很遗憾,但我无法理解作者为何如此实施ScheduledExecutorService
。
当然,通常不应该捕获RuntimeException或Error,尤其是Error。但实际上,特别是在RuntimeException的情况下,事实是它们在生产部署中非常普遍,我觉得几乎总是希望当特定操作失败时,应用程序本身不会因为孤立的错误而失败。
确实,抑制一个周期性任务不会影响其他类型的周期性任务。但鉴于大多数周期性任务的性质,这些任务不应该被视为“服务”,而不是孤立的任务吗?
换句话说,不应该只有importantPeriodicTask
的一个实例失败,并且任务本身会继续被重新安排吗?
答案 0 :(得分:3)
在我看来,目前的行为是合理的。 RuntimeExceptions通常引用错误。它们实际上可以出现在任务代码中的任何位置。例如,如果任务是有状态的,则可能使其状态不一致,并且后续执行将具有意外行为。一般来说,我不喜欢试图从自己的错误中恢复的代码,但这是我的看法。
如果您希望更改ScheduledExecutorService的行为,请查看以下通用解决方案: