5

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

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

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

执行器由Executors.newSingleThreadScheduledExecutor()多个任务创建并运行,但它们都安排在几个小时之内,最多需要几分钟。

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

我注意到,在使用 JDK 1.7.0_03 的 Windows 2003 Server 上,任务每天会延迟近 10 秒。每月大约需要 5 分钟,这对于我的申请来说是可以接受的。无论如何,我可能不得不实施重新调度,因为我希望任务在特定的本地时间运行,所以我必须自己处理 DST。该服务运行时间很长——半年不重启并不稀奇。

尽管如此,我认为对于一个大部分空闲的系统来说,每天 10 秒的不准确性是相当高的,我想知道我是否应该为更糟糕的行为做好准备。

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

4

1 回答 1

3

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

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

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

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

于 2013-01-10T10:30:01.197 回答