nanoTime和currentTimeMillis在Mac OS上有不同的费率

时间:2016-05-24 15:01:01

标签: java macos

我正在尝试使用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()来衡量持续时间。但在这种情况下,我不确定这是真的。

有人可以详细说明这个话题吗?

2 个答案:

答案 0 :(得分:0)

如果您正在使用NTP,则很可能您的currentTimeMillis正在被更正,因此它是最可能正确的。 nanoTime()基于时钟周期/时钟频率。如果此频率略微偏离测量,您将看到恒定的漂移。这不应该基于Java的版本,而应该基于操作系统和硬件。

答案 1 :(得分:0)

两人都撒谎:)

无法以绝对精度测量时间。计算机中的每个计时器都会有轻微的漂移。由于currentTimeMillis和nanoTime可能来自不同的计时器,因此您可以完全自然地观察到两者之间的漂移。根据您的计算机运行状态,漂移甚至可以变化(例如,机器上的工作负载可能会改变其温度,进而导致时钟发生器的轻微变化。这些影响很小,但它们总是在那里)。

在似乎没有漂移的情况下,currentTimeMillis和nanoTime都由相同的硬件定时器驱动,或者在OS或VM中都有校正机制。