ScheduledThreadPoolExecutor 由于 CPU 时间差异而执行错误时间
我正在使用 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
差异是 16ms 但 4011374001ns (或 40,113ms)
所以看起来像两个 CPU 时钟之间存在 40 秒的差异
如何在 java 代码中解决此问题?不幸的是,这是一台客户端机器,我无法修改他们的系统。
I'm scheduling a task using a ScheduledThreadPoolExecutor object. I use the following method:
public ScheduledFuture<?> schedule(Runnable command, long delay,TimeUnit unit)
and set the delay to 30 seconds (delay = 30,000 and unit=TimeUnit.MILLISECONDS). Sometimes my task occurs immediately and other times it takes 70 seconds.
I believe the ScheduledThreadPoolExecutor uses CPU specific clocks. When i run tests comparing System.currentTimeMillis(), System.nanoTime() [which is CPU specific] i see the following
schedule: 1272637682651ms, 7858346157228410ns
execute: 1272637682667ms, 7858386270968425ns
difference is 16ms but 4011374001ns (or 40,113ms)
so it looks like there is discrepancy between two CPU clocks of 40 seconds
How do i resolve this issue in java code? Unfortunately this is a clients machine and i can't modify their system.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,你说得对,ScheduledThreadPoolExecutor 使用 System.nanoTime()。而且您也认为 System.nanoTime() 依赖于特定的系统实例。如果您的流程碰巧在计划和执行之间迁移,那么您就不走运了。 (我不认为多 CPU 系统上的 CPU 之间的迁移会很重要,但也许会很重要?如果您在 VM 中运行并且 VM 在主机之间迁移,那么当然会很重要)。
我认为在这种情况下唯一真正的解决方案是使用除 ScheduledThreadPoolExecutor 之外的其他东西...这也不是仅仅更改 ScheduledThreadPoolExecutor.now() 那么简单。 AbstractQueuedSynchronizer$ConditionObject.awaitNanos() 也使用 System.nanoTime() 。
我的一个项目使用 Quartz 进行作业调度,我从未见过您描述的问题图书馆。我不知道实现细节(也许它也只使用 System.nanoTime(),但也许不是?)。
Yes, you're right that ScheduledThreadPoolExecutor uses System.nanoTime(). And you're also right that System.nanoTime() is dependent on the particular system instance. If your process happens to migrate between schedule and execute, then you're out of luck. (I wouldn't think that migrating between CPUs on a multi-CPU system would matter, but maybe it does? Certainly it would matter if you're running in a VM and the VM migrated between hosts).
I think the only real solution in this case is to use something other than ScheduledThreadPoolExecutor... It's not a simple as just changing ScheduledThreadPoolExecutor.now() either. AbstractQueuedSynchronizer$ConditionObject.awaitNanos() uses System.nanoTime() too.
One of my projects uses Quartz for job scheduling and I've never seen the problem you describe with that library. I don't know the implementation details (maybe it just uses System.nanoTime() too, but maybe not?).