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
对象实际上可以携带纳秒精度)。
代码(也可以适用于 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[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/