Точность часов Java в Windows: 15-16 мс - PullRequest
0 голосов
/ 25 апреля 2018

В последнее время точность часов в Windows, похоже, изменилась.Я помню, что он был очень точным, начиная с Windows 7 (разрешение 1 мс), и теперь время скачкообразно изменяется с шагом 15-16 мс.Я заметил, что из-за сбоя некоторых (хотя и плохо написанных) модульных тестов (тесты проверили, что между записью и чтением прошло некоторое время).

Это влияет на следующие реализации:

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

Мне хорошо известно, что истекшее время должно измеряться с использованием System.nanoTime() deltas, но мне все же интересно, пропустил ли я что-то, что вернуло разрешение часов на 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--;
        }
    }
}

1 Ответ

0 голосов
/ 26 апреля 2018

Чтобы получить местное время с наилучшей точностью независимо от платформы , я придумал решение, основанное на текущем времени (измерение при его увеличении) в качестве привязки, а также и смещении. основано на System.nanoTime() дельтах.

Преимущества:

  • текущее время с точностью, не зависящей от платформы
  • высокая точность (нано время)
  • переносной (поскольку объекты java.time могут действительно иметь наносекундную точность).

Код (может быть адаптирован для обслуживания LocalTime и LocalDateTime):

/**
 * 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 [Европа / Цюрих] 2018-04-26T12: 51: +02,293524865 + 02: 00 [Европа / Цюрих] 2018-04-26T12: 51: +02,293598126 + 02: 00 [Европа / Цюрих] 2018-04-26T12: 51: +02,293660770 + 02: 00 [Европа / Цюрих] 2018-04-26T12: 51: +02,293725538 + 02: 00 [Европа / Цюрих]

...