You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

无需JNI如何获取绝对纳秒时间?

实现跨JVM的高精度绝对纳秒时间

相信不少人都遇到过这个矛盾:System.currentTimeMillis()能拿到跨虚拟机通用的绝对时间,但精度只有毫秒级,对付不了高要求的场景;而System.nanoTime()虽然有纳秒级精度,但它返回的是自某个固定但完全随机的内部起始点以来的纳秒数——这个起始点是JVM自己维护的,和绝对时间不挂钩,没法直接用来做跨JVM的时间对比。

不过这里有个很巧妙的解决办法:如果我们能提前拿到两个固定不变的参考值,就能用简单的数学运算把System.nanoTime()转换成跨JVM可用的绝对纳秒时间,而且计算速度和调用System.currentTimeMillis()差不多,因为那两个参考值只会在JVM启动时取一次,之后再也不会变。

具体来说,我们需要的两个关键参考值是:

  • JVM启动时的绝对毫秒时间:可以用ManagementFactory.getRuntimeMXBean().getStartTime()获取,这个值和System.currentTimeMillis()的时间基准完全一致
  • JVM启动时的System.nanoTime()值:在JVM启动初期调用一次System.nanoTime()记录下来就好

之后,任何时刻想要获取绝对纳秒时间,只需要套用这个公式:

long absoluteNanoTime = jvmStartupMillis * 1_000_000 + (System.nanoTime() - nanoTimeAtStartup);

说白了,这个逻辑就是给System.nanoTime()的相对时间找了个绝对锚点——把JVM启动时的绝对时间转成纳秒,再加上从启动到当前时刻的纳秒增量,这样得到的结果既有纳秒级精度,又和通用的绝对时间基准对齐,自然就能跨JVM使用了。

需要注意的是,这两个参考值最好在JVM启动后尽早获取,不过就算晚一点,两者的时间差也微乎其微,几乎不会影响最终结果的精度。

内容的提问来源于stack exchange,提问作者vach

火山引擎 最新活动