我正在尝试使用System.nanoTime()
和System.currentTimeMillis()
衡量某段时间的持续时间。周期越长,我从两次测量中获得的差异越大。
这是一个展示问题的小片段:
public class TimeTest {
public static void main(String[] args) throws Exception {
long startNanos = System.nanoTime();
long startMillis = System.currentTimeMillis();
while (true) {
long nowNanos = System.nanoTime();
long nowMillis = System.currentTimeMillis();
System.out.println((nowMillis - startMillis) - (nowNanos - startNanos) / 1000000);
Thread.sleep(100);
}
}
}
在使用jdk 1.8.0_74的Mac OS上运行时,有一个明显的趋势,即每分钟值下降约2ms。即起初我只看到0和1,但在10分钟后,有大约-20的值。
我设法仅在mac上使用jdk8观察此类行为,无法在Linux和Windows上同时使用jdk 7和8重现它。
所以,问题是:谁在撒谎?我知道应该首选nanoTime()
来衡量持续时间。但在这种情况下,我不确定这是真的。
有人可以详细说明这个话题吗?
答案 0 :(得分:0)
如果您正在使用NTP,则很可能您的currentTimeMillis正在被更正,因此它是最可能正确的。 nanoTime()基于时钟周期/时钟频率。如果此频率略微偏离测量,您将看到恒定的漂移。这不应该基于Java的版本,而应该基于操作系统和硬件。
答案 1 :(得分:0)
两人都撒谎:)
无法以绝对精度测量时间。计算机中的每个计时器都会有轻微的漂移。由于currentTimeMillis和nanoTime可能来自不同的计时器,因此您可以完全自然地观察到两者之间的漂移。根据您的计算机运行状态,漂移甚至可以变化(例如,机器上的工作负载可能会改变其温度,进而导致时钟发生器的轻微变化。这些影响很小,但它们总是在那里)。
在似乎没有漂移的情况下,currentTimeMillis和nanoTime都由相同的硬件定时器驱动,或者在OS或VM中都有校正机制。