V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Richard14
V2EX  ›  Java

Java 中高精度计时?

  •  
  •   Richard14 · 2022-07-19 06:10:37 +08:00 · 3132 次点击
    这是一个创建于 645 天前的主题,其中的信息可能已经有所发展或是发生改变。

    根据廖雪峰教学博客,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()?

    21 条回复    2022-07-21 12:29:01 +08:00
    zzl22100048
        1
    zzl22100048  
       2022-07-19 06:48:51 +08:00 via iPhone
    计算时间差用 nanotime
    Instant.now()是静态工厂方法,是构造函数的语义化封装
    Aloento
        2
    Aloento  
       2022-07-19 06:52:30 +08:00
    每个平台都有一个最小时间精度,Windows 的间隔最大,Java 自己也有损
    Procumbens
        3
    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
        4
    FYFX  
       2022-07-19 08:15:23 +08:00
    Instant.now() 是静态工厂方法,要想深入了解的话可以看 effective java
    sprit
        5
    sprit  
       2022-07-19 09:24:06 +08:00
    Spring StopWatch
    Richard14
        6
    Richard14  
    OP
       2022-07-19 09:28:32 +08:00
    @Procumbens 最佳实践学习一个,不过我代码里两个 instance 时间一致可能是什么导致的?同步 IO 都很费时啊
    LeegoYih
        7
    LeegoYih  
       2022-07-19 09:35:09 +08:00
    1 纳秒时间,光都只能走 0.299792458 米,区区 Java 何德何能
    senninha
        8
    senninha  
       2022-07-19 09:38:49 +08:00
    这是浮点数丢精度了。
    senninha
        9
    senninha  
       2022-07-19 09:44:44 +08:00
    @senninha 看了一下实现,SystemClock 本来就是毫秒精度。。
    ```
    @Override
    public Instant instant() {
    return Instant.ofEpochMilli(millis());
    }
    ```
    Richard14
        10
    Richard14  
    OP
       2022-07-19 09:52:20 +08:00
    @zzl22100048 在后面设计模式的章节里查了一下工厂方法。。似乎就是一个类的静态方法返回新的实例。。所以就变成了

    类.静态方法() -> return new Object() 类似这样的。。。。
    Mithril
        11
    Mithril  
       2022-07-19 10:01:14 +08:00   ❤️ 2
    “纳秒级精度”不代表它有“纳秒级准确度”。
    你是不可能在一个只有毫秒级时钟的系统上,获取准确的纳秒级时间的。
    更别说还是非实时系统了。
    pannanxu
        12
    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
        13
    wowo243  
       2022-07-19 10:19:56 +08:00
    试试 StopWatch
    BBCCBB
        14
    BBCCBB  
       2022-07-19 10:27:41 +08:00
    统计耗时用 System.nanoTime, 其他的基本都是 System.currentTimeMillis 的封装. nanoTime 性能消耗比 currentTimeMillis 小的多, 但 nanoTime 不能拿来获取 Unix time, 基本智能用来统计耗时.
    tairan2006
        15
    tairan2006  
       2022-07-19 11:15:34 +08:00
    纳秒精度属实想多了
    aguesuka
        16
    aguesuka  
       2022-07-19 12:59:16 +08:00
    windows 是 0, 而 linux 有值, 尽管用 double 表示 96 有效数字然后只关注最后几位很离谱, 而且是 [软工类工作,面试考察底层知识是否合理](v2ex.com/t/865329) 的楼主写的.
    newmlp
        17
    newmlp  
       2022-07-19 13:55:19 +08:00
    java 是不可能,c/c++还是可以的
    murmur
        18
    murmur  
       2022-07-19 13:57:07 +08:00
    高精度计时你需要 fpga

    c++也不行

    这玩意必须硬件时钟
    NoKey
        19
    NoKey  
       2022-07-19 14:20:48 +08:00
    java 这个层面,毫秒已经足够了
    newmlp
        20
    newmlp  
       2022-07-19 14:33:18 +08:00
    @murmur rdtsc 了解一下
    zjp
        21
    zjp  
       2022-07-21 12:29:01 +08:00 via Android
    System.nanoTime 的精度可以参考这里
    https://shipilev.net/blog/2014/nanotrusting-nanotime/
    Instant 是基于毫秒的就算了...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1369 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 17:36 · PVG 01:36 · LAX 10:36 · JFK 13:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.