【问题标题】:ScheduledThreadPoolExecutor executing a wrong time because of CPU time discrepancy由于 CPU 时间差异,ScheduledThreadPoolExecutor 执行错误的时间
【发布时间】:2010-04-30 15:55:28
【问题描述】:

我正在使用 ScheduledThreadPoolExecutor 对象调度任务。我使用以下方法:

public ScheduledFuture<?> schedule(Runnable command, long delay,TimeUnit unit) 

并将延迟设置为 30 秒(延迟 = 30,000 且单位=TimeUnit.MILLISECONDS)。有时我的任务会立即执行,有时需要 70 秒。

我相信 ScheduledThreadPoolExecutor 使用 CPU 特定的时钟。当我运行比较 System.currentTimeMillis()、System.nanoTime() [这是 CPU 特定的] 的测试时,我看到以下内容

时间表:1272637682651ms,7858346157228410ns

执行:1272637682667ms,7858386270968425ns

差异是 16 毫秒,但 4011374001ns(或 40,113 毫秒)

所以看起来两个 40 秒的 CPU 时钟之间存在差异

如何在 java 代码中解决这个问题?不幸的是,这是一台客户端机器,我无法修改他们的系统。

【问题讨论】:

  • 棘手的一个。也许java.util.Calendar 会有所帮助? Calendar.getInstance() 等等..
  • 您是否在虚拟机(VMWare、KVM、Virtual PC)上运行此代码?即使在毫秒级别,虚拟化也会对 CPU 时钟造成严重破坏。
  • 它直接在 Windows XP Professional 机器上运行。没有虚拟化。

标签: java concurrency java.util.concurrent


【解决方案1】:

是的,ScheduledThreadPoolExecutor 使用 System.nanoTime() 是对的。而且您也说对了 System.nanoTime() 取决于特定的系统实例。如果您的流程碰巧在计划和执行之间迁移,那么您就不走运了。 (我不认为在多 CPU 系统上的 CPU 之间迁移会很重要,但也许确实如此?如果您在虚拟机中运行并且虚拟机在主机之间迁移,这当然会很重要)。

我认为在这种情况下唯一真正的解决方案是使用 ScheduledThreadPoolExecutor 以外的其他东西......这也不是仅仅更改 ScheduledThreadPoolExecutor.now() 那么简单。 AbstractQueuedSynchronizer$ConditionObject.awaitNanos() 也使用 System.nanoTime()。

我的一个项目使用Quartz 进行作业调度,我从未见过你描述的那个库的问题。我不知道实现细节(也许它也只是使用 System.nanoTime(),但也许不是?)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 2018-06-21
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    • 1970-01-01
    相关资源
    最近更新 更多