正常OS/JVM上ScheduledExecutorService的准确性

Chr*_*ris 5 java scheduled-tasks

我ScheduledExecutorService.scheduleAtFixedRate用来运行日常任务,如下所示:

executor.scheduleAtFixedRate(task, d, 24L * 3600 * 1000, TimeUnit.MILLISECONDS);
Run Code Online (Sandbox Code Playgroud)

(d是以毫秒为单位的初始延迟).

执行程序由Executors.newSingleThreadScheduledExecutor()多个任务创建并运行多个任务,但它们都是相隔几个小时安排的,最多只需几分钟.

我知道ScheduledExecutorService不保证准确性,我需要一个实时操作系统和JVM来实现这一点.但是,这不是我的任务的要求.

我注意到在Windows 2003 Server上,使用JDK 1.7.0_03,任务每天下滑几乎10秒.每个月大约需要5分钟,这对我的申请来说是可以接受的.我可能不得不实施重新安排,因为我希望任务在特定的当地时间运行,所以我必须自己处理DST.该服务运行很长一段时间 - 没有重启的半年也不是那么罕见.

尽管如此,我认为对于大多数闲置的系统而言,10秒/天的不准确度相当高,我想知道我是否应该为更糟糕的行为做好准备.

所以我的问题是你的经历scheduleAtFixedRate.10秒/天正常吗?我会在其他环境中获得更好或更差的准确度(我们的客户也使用Linux和Solaris服务器)吗?或者10秒是否表明我们的环境出现问题?

Pet*_*rey 3

对于一个长时间运行的任务来说,这并不奇怪。您遇到的另一个问题是它使用的 nanoTime() 不与 NTP 等同步。这可能会导致挂钟发生漂移。

避免这种情况的一种方法是按照您的建议重复安排。重复任务实际上会自行重新安排(这就是为什么它们不能抛出异常,请参见下文)。您可以使用一个一次性任务,在最后使用挂钟时间并考虑到日列表节省来自行重新安排。

顺便说一句:我会确保你捕获异常,甚至抛出 Throwable。如果你不这样做,你的任务将停止,可能会默默地停止(除非你正在查看返回的 Future 对象)

我所做的就是稍微作弊。我有一个任务每 1 - 10 秒唤醒一次并检查它是否需要运行,如果不需要则返回。如果您没有数千个任务,那么开销通常是微不足道的,并且实现起来要简单得多。