Java中的Timer类如何对系统时钟敏感?

时间:2013-09-14 16:12:14

标签: java timer

关于TimerScheduledThreadPoolExecutor之间差异的highly voted answer on SO,在列举差异时会提到以下内容:

  

定时器可能对系统时钟的变化很敏感,   ScheduledThreadPoolExecutor不是。

以上是在Java Concurrency in Practice这本伟大的书中逐字提到的。

除了上面提到的那个,我理解答案中提到的要点。说Timers对系统时钟敏感而ScheduledThreadPoolExecutors不是这样的,这是什么意思?

3 个答案:

答案 0 :(得分:9)

Timer使用System.currentTimeMillis()代表挂钟时间,绝不应该用于检查相对时间,例如确定运行时间长度,或者在这种情况下,在执行任务之前要延迟多长时间。 System.currentTimeMillis()会受到自动调整系统时钟或甚至手动更改系统时钟等因素的影响。因此,如果你打电话两次并检查你得到的时间之间的差异,你甚至可以得到一个负数。

另一方面,

System.nanoTime()专门用于测量经过时间,应该用于此类事情。

答案 1 :(得分:5)

Timer使用System.currentTimeMillis()来确定下一次执行任务。

ScheduledThreadPoolExecutor使用System.nanoTime()

同样nanoTime()方法只能用于衡量已用时间,与系统或挂钟时间的任何其他概念无关。

System.currentTimeMillis() 敏感到系统时钟

System.nanoTime() 对系统时钟不敏感,因为它会测量经过的时间。

Java文档:System.nanoTime()

  

此方法只能用于测量经过的时间而不是   与系统或挂钟时间的任何其他概念有关。价值   返回表示自固定但任意时间以来的纳秒   (也许在将来,所以价值可能是负面的。)

答案 2 :(得分:1)

查看源代码,Timer类使用System.currentTimeMillis()计划任务。 ScheduledThreadPoolExecutor使用System.nanoTime()

currentTimeMillis()将倾向于使用OS时钟,即追踪当前日期/时间的时钟。 nanoTime()将倾向于使用更高分辨率的硬件时钟。

如果您将操作系统时钟移回一小时,那么currentTimeMillis()可能会反映nanoTime()不应该。{/ p>