Windows 上的 Java 时钟精度 : 15-16ms

标签 java windows java-time

Windows 上的时钟精度最近似乎发生了变化。我记得自 Windows 7(1 毫秒分辨率)以来它非常准确,现在时间以 15 到 16 毫秒的步长跳跃。我注意到由于一些(尽管写得不好)单元测试失败(测试检查写入和读取记录之间经过了一段时间)。

这会影响以下实现:

  • System.currentTimeMillis()
  • LocalTime.now()
  • LocalDateTime.now()
  • ZonedDateTime.now()

我很清楚耗时是使用 System.nanoTime() 增量来测量的,但我想知道我是否错过了将时钟分辨率改回到 15-16 毫秒的东西.

环境:

  • Windows 10 版本 1709
  • JRE/JDK 1.8.0_171-b11(64 位)

有没有人也注意到这一点?此分辨率更改的原因可能是什么?

编辑:
检查此行为的测试代码(查看输出:时间变化和变化前的样本数)

@Test
public void testCurrentTimeMillis() {
    test(() -> System.currentTimeMillis());
}

@Test
public void testNanoTime() {
    test(() -> System.nanoTime());
}

@Test
public void testLocalTime() {
    test(() -> LocalTime.now());
}

@Test
public void testLocalDateTime() {
    test(() -> LocalDateTime.now());
}

@Test
public void testZonedDateTime() {
    test(() -> ZonedDateTime.now());
}

private <T> void test(Supplier<T> timeSupplier) {

    int samples = 20;
    String lastTimeString = null;
    int count = 0;
    while (samples > 0) {

        count++;
        String timeString = timeSupplier.get().toString();
        if (!timeString.equals(lastTimeString)) {
            System.out.println(timeString + " (" + count + ")");
            lastTimeString = timeString;
            count = 0;
            samples--;
        }
    }
}

最佳答案

为了获得无论平台如何都具有最佳精度的本地时间,我想出了一个解决方案,它基于当前时间(测量何时增加)作为 anchor ,并且基于 System.nanoTime() 增量的偏移量。

优点:

  • 不依赖于平台的精确当前时间
  • 高精度(纳秒级)
  • 可移植(因为 java.time 对象实际上可以携带纳秒精度)。

代码(也可以适用于 LocalTimeLocalDateTime):

/**
 * Exact zoned date/time, compensates for the 15-16ms leaps 
 * of milliseconds time on some Java platforms.
 */
public final class ExactZonedDateTime {

    private static ZonedDateTime anchor;
    private static long anchorNanos;

    static {
        ZonedDateTime last = ZonedDateTime.now();
        while (((anchor = ZonedDateTime.now()).equals(last))) {
            anchorNanos = System.nanoTime();
        }
    }

    private ExactZonedDateTime() {
    }

    public static ZonedDateTime now() {
        return anchor.plusNanos(System.nanoTime() - anchorNanos);
    }
}

后续调用:

2018-04-26T12:51:02.293079632+02:00[Europe/Zurich] 2018-04-26T12:51:02.293524865+02:00[Europe/Zurich] 2018-04-26T12:51:02.293598126+02:00[Europe/Zurich] 2018-04-26T12:51:02.293660770+02:00[Europe/Zurich] 2018-04-26T12:51:02.293725538+02:00[Europe/Zurich]

关于Windows 上的 Java 时钟精度 : 15-16ms,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50023261/

相关文章:

java - 在 Java 中解析日期时间字符串是否需要 `Locale`?

java - 如何将 Jmeter 变量保存到 csv 文件

java - java.time 是否无法解析秒数?

java - 客户端服务器程序未建立连接

python - 使用 GUI 运行 Python 脚本时如何摆脱 "Command Line"窗口?

c - 为什么我无法创建此文件?

windows - 无法使用 powershell 从 32 位版本的 win2008 读取 64 位注册表项

java - 如何表示和操作大于 24 :00 in Java? 的时间值

java - 使用 Play 框架覆盖 HTTP 方法

java - 初学者 Android : ListView to affect the next class