Java 中高精度计时?

2022-07-19 06:10:37 +08:00
 Richard14

根据廖雪峰教学博客,java 中处理日期 /时间问题,如无特殊必要应优先采用较新的 java.time 模块。

一个疑问是,写码时常见需求是获取两点之间执行时间。按照该博客说明,精度最高的应该是 Instant 类,所以计算两点间代码执行时间应该可以使用下列代码:

public class Main {
    public class void Main() {
        var start = Instant.now();
        // ... run some code
        System.out.println("done");
        var end = Instant.now();
        System.out.println(instantToDouble(end) - instantToDouble(start));
    }
    
    protected static double instantToDouble(Instant instant) {
    	return instant.getEpochSecond() + instant.getNano() / 1e9;
    }
}

实际得到结果两点间差值是 0.0 ,两个 instant 获得的时间完全一致,让人疑惑因为 instant 理论上是纳秒级精度,而两点之间执行了 sout 代码,sout 根据廖旭峰的说明是一个同步 IO ,所以理论上上述代码不应该输出 0 ,导致它输出 0 的原因是什么呢? instant 精度不够吗,或者 io 流的问题?


另外再顺便问下 instant 是什么设计,导入是通过 import java.time.*导入的,正常来说创建对象应该是用类似 var instant = new Instant().now();这种感觉的句子,为什么 instant 可以直接 var instant = Instant.now()?

3140 次点击
所在节点    Java
21 条回复
zzl22100048
2022-07-19 06:48:51 +08:00
计算时间差用 nanotime
Instant.now()是静态工厂方法,是构造函数的语义化封装
Aloento
2022-07-19 06:52:30 +08:00
每个平台都有一个最小时间精度,Windows 的间隔最大,Java 自己也有损
Procumbens
2022-07-19 08:10:15 +08:00
不需要自己定义一个 instantToDouble 。要比较 start 和 end 就

Duration timeElapsed = Duration.between(start, end);
System.out.println(timeElapsed.toNanos()); // 或者精确到毫秒: timeElapsed.toMillis()
FYFX
2022-07-19 08:15:23 +08:00
Instant.now() 是静态工厂方法,要想深入了解的话可以看 effective java
sprit
2022-07-19 09:24:06 +08:00
Spring StopWatch
Richard14
2022-07-19 09:28:32 +08:00
@Procumbens 最佳实践学习一个,不过我代码里两个 instance 时间一致可能是什么导致的?同步 IO 都很费时啊
LeegoYih
2022-07-19 09:35:09 +08:00
1 纳秒时间,光都只能走 0.299792458 米,区区 Java 何德何能
senninha
2022-07-19 09:38:49 +08:00
这是浮点数丢精度了。
senninha
2022-07-19 09:44:44 +08:00
@senninha 看了一下实现,SystemClock 本来就是毫秒精度。。
```
@Override
public Instant instant() {
return Instant.ofEpochMilli(millis());
}
```
Richard14
2022-07-19 09:52:20 +08:00
@zzl22100048 在后面设计模式的章节里查了一下工厂方法。。似乎就是一个类的静态方法返回新的实例。。所以就变成了

类.静态方法() -> return new Object() 类似这样的。。。。
Mithril
2022-07-19 10:01:14 +08:00
“纳秒级精度”不代表它有“纳秒级准确度”。
你是不可能在一个只有毫秒级时钟的系统上,获取准确的纳秒级时间的。
更别说还是非实时系统了。
pannanxu
2022-07-19 10:06:14 +08:00
guava 秒表:

```java
Stopwatch started = Stopwatch.createStarted();
Thread.sleep(1000);
long s = started.stop().elapsed(TimeUnit.MILLISECONDS);
```
wowo243
2022-07-19 10:19:56 +08:00
试试 StopWatch
BBCCBB
2022-07-19 10:27:41 +08:00
统计耗时用 System.nanoTime, 其他的基本都是 System.currentTimeMillis 的封装. nanoTime 性能消耗比 currentTimeMillis 小的多, 但 nanoTime 不能拿来获取 Unix time, 基本智能用来统计耗时.
tairan2006
2022-07-19 11:15:34 +08:00
纳秒精度属实想多了
aguesuka
2022-07-19 12:59:16 +08:00
windows 是 0, 而 linux 有值, 尽管用 double 表示 96 有效数字然后只关注最后几位很离谱, 而且是 [软工类工作,面试考察底层知识是否合理](v2ex.com/t/865329) 的楼主写的.
newmlp
2022-07-19 13:55:19 +08:00
java 是不可能,c/c++还是可以的
murmur
2022-07-19 13:57:07 +08:00
高精度计时你需要 fpga

c++也不行

这玩意必须硬件时钟
NoKey
2022-07-19 14:20:48 +08:00
java 这个层面,毫秒已经足够了
newmlp
2022-07-19 14:33:18 +08:00
@murmur rdtsc 了解一下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/867144

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX