Windows上的Java时钟精度:15-16ms
Windows上的时钟精度最近似乎发生了变化。我记得自从Windows 7(1毫秒分辨率)以来,它非常准确,现在时间以15到16毫秒的步长跳跃。我注意到,由于一些单元测试失败(尽管写得很糟糕)(测试检查了写入和读取记录之间经过的时间) 这会影响以下实现:Windows上的Java时钟精度:15-16ms,java,windows,java-time,Java,Windows,Java Time,Windows上的时钟精度最近似乎发生了变化。我记得自从Windows 7(1毫秒分辨率)以来,它非常准确,现在时间以15到16毫秒的步长跳跃。我注意到,由于一些单元测试失败(尽管写得很糟糕)(测试检查了写入和读取记录之间经过的时间) 这会影响以下实现: System.currentTimeMillis() LocalTime.now() LocalDateTime.now() ZoneDateTime.now() 我很清楚,要使用System.nanoTime()delta来测量经过的时间
System.currentTimeMillis()
LocalTime.now()
LocalDateTime.now()
ZoneDateTime.now()
System.nanoTime()
delta来测量经过的时间,但我想知道是否错过了将时钟分辨率改回15-16ms的内容
环境:
- Windows10版本1709
- JRE/JDK1.8.0_171-b11(64位)
检查此行为的测试代码(请参阅输出:时间更改和更改前的样本数)
@测试
公共无效testCurrentTimeMillis(){
测试(()->System.currentTimeMillis());
}
@试验
公共void testNanoTime(){
测试(()->System.nanoTime());
}
@试验
public void testLocalTime(){
test(()->LocalTime.now());
}
@试验
public void testLocalDateTime(){
test(()->LocalDateTime.now());
}
@试验
公共无效TestZoneDateTime(){
测试(()->ZoneDateTime.now());
}
专用无效测试(供应商时间供应商){
int样本=20;
字符串lastTimeString=null;
整数计数=0;
而(样本数>0){
计数++;
String timeString=timeSupplier.get().toString();
如果(!timeString.equals(lastTimeString)){
System.out.println(timeString+“(“+count+”));
lastTimeString=timeString;
计数=0;
样本--;
}
}
}
为了在不考虑平台的情况下以最佳精度获得本地时间,我提出了一个解决方案,它基于当前时间(增加时测量)作为锚定,并基于System.nanoTime()
增量进行偏移
优点:
- 精度不取决于平台的当前时间
- 高精度(纳米时间)
- 可移植(正如
对象实际上可以携带纳秒精度)java.time
LocalTime
和LocalDateTime
):
后续电话:
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[欧洲/苏黎世]
你打开了windows开发者模式吗?@ShanuGupta:没有,它关闭了(在“侧载应用程序”中),你能打开并再次检查吗?您可能必须重新启动系统。可能与@OleV.V重复。另一个问题可以追溯到2009年,当时这种错误在32位Windows平台上很常见。我的案例是最近的一个64位Windows平台,问题再次出现。
@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--;
}
}
}
/**
* 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);
}
}