【问题标题】:Accuracy of ScheduledExecutorService on normal OS / JVMScheduledExecutorService 在正常 OS / JVM 上的准确性
【发布时间】:2013-01-10 10:09:24
【问题描述】:

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

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

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

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

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

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

不过,我认为对于大部分空闲的系统来说,每天 10 秒的误差是相当高的,我想知道我是否应该为更糟糕的行为做好准备。

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

【问题讨论】:

  • 注意:24L * 3600 * 1000, TimeUnit.MILLISECONDS 等同于 1, TimeUnit.DAYS... 这就是时间单位的全部意义:避免时间单位转换!
  • @assylias 是的,但是 initialDelay d 以毫秒为单位,并且只有一个 TimeUnit 参数。
  • 我会使用 Quartz 或 Spring task:scheduled-tasks 在特定的当地时间触发,那么你就没有这个问题。
  • 您在该 ScheduledExecutor 中只运行一项任务吗?如果不是,它有多少个线程?会不会是因为一项任务耽误了其他任务?
  • @assylias 哦,好问题,因为我使用了signgleThreadExecutor。我已经编辑了这个问题来描述这一点。我认为其他任务在这里不重要。

标签: java scheduled-tasks


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 2023-01-16
    相关资源
    最近更新 更多