为什么ScheduledExecutorService在抛出exception后不再运行任务?

为了执行定期任务,我查看了TimerScheduledThreadPoolExecutor (使用单个线程)并决定使用后者,因为在reference for Executors.newSingleThreadScheduledExecutor()reference for Executors.newSingleThreadScheduledExecutor() ,它说:

但请注意,如果此单个线程由于在关闭之前执行期间的故障而终止,则在需要执行后续任务时将使用新线程。

我的计划是使用它作为一个保护措施,以防止我希望监视其他操作的监视程序代码中未被捕获的exception。 我想确认并编写下面的测试,该测试很快就失败了。 看来我做错了假设,或者我的测试出了什么问题?

这是代码:

 @Test public void testTimer() { final AtomicInteger cTries = new AtomicInteger(0); final AtomicInteger cSuccesses = new AtomicInteger(0); TimerTask task = new TimerTask() { @Override public void run() { cTries.incrementAndGet(); if (true) { throw new RuntimeException(); } cSuccesses.incrementAndGet(); } }; /* Timer t = new Timer(); t.scheduleAtFixedRate(task, 0, 500); */ ScheduledExecutorService exe = Executors.newSingleThreadScheduledExecutor(); exe.scheduleAtFixedRate(task, 0, 500, TimeUnit.MILLISECONDS); synchronized (this) { try { wait(3000); } catch (InterruptedException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } exe.shutdown(); /* t.purge(); */ Assert.assertEquals(cSuccesses.get(), 0); Assert.assertTrue(cTries.get() > 1, String.format("%d is not greater than 1. :(", cTries.get())); } 

一旦重复任务抛出未捕获的exception,就会假定它已经死亡或处于错误状态。 除非你检查Future以获得Error / Exception,否则它也会无声地失败。

如果您不想杀死重复任务,则必须捕获exception。


正如亚光b在上面的评论中指出的,

对于像这样的框架代码来说,假设它可以安全地重新启动失败的作业,这将是一个问题 – 它因exception而失败意味着数据可能已经处于任何类型的状态,并且可能重新启动它是不安全的。工作。

亚光b给出了原因。

对于像这样的框架代码来说,假设它可以安全地重新启动失败的作业,这将是一个问题 – 它因exception而失败意味着数据可能已经处于任何类型的状态,并且可能重新启动它是不安全的。工作。

应该注意的是,它写在ScheduledExecutorService的文档中

如果任务的任何执行遇到exception,则后续执行被禁止。

正如Michael Krusse所说,关于创建新线程的观点是允许其他任务继续运行。