正常OS / JVM上ScheduledExecutorService的准确性

时间:2013-01-10 10:09:24

标签: java scheduled-tasks

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

executor.scheduleAtFixedRate(task, d, 24L * 3600 * 1000, TimeUnit.MILLISECONDS);

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

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

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

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

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

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

1 个答案:

答案 0 :(得分:2)

对于一项长期运行的任务,这并不太令人惊讶。您遇到的另一个问题是它使用的nanoTime()与NTP等不同步。这可能会导致挂钟漂移。

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

顺便说一句:我会确保你抓住一个例外,甚至扔掉了Throwable。如果你不这样做,你的任务就会停止,可能是静默的(除非你正在查看返回的Future对象)

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