> 文章列表 > JAVA System.nanoTime()与GO time.Now().UnixNano()区别

JAVA System.nanoTime()与GO time.Now().UnixNano()区别

JAVA System.nanoTime()与GO time.Now().UnixNano()区别

JAVA System.nanoTime()

    public static void main(String[] args) {long nano = System.nanoTime();System.out.println(nano);}

输出:701863191254000,这个值有点奇怪,System.currentTimeMillis()不是System.nanoTime()的1000000倍。

这个值是个什么值,先看一点源码注释:

Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds.
返回正在运行的Java虚拟机的高分辨率时间源的当前值,单位为纳秒。
(我理解就是指,这个纳秒值就是Java虚拟机能获取的最高精度的时间值了。)This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary origin time (perhaps in the future, so values may be negative). The same origin is used by all invocations of this method in an instance of a Java virtual machine; other virtual machine instances are likely to use a different origin.
这种方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。返回的值表示自某个固定但任意的起始时间以来的纳秒(可能在将来,因此值可能为负值)。在Java虚拟机的实例中,此方法的所有调用都使用相同的原点;其他虚拟机实例可能使用不同的来源。
(1、这个纳秒时间跟标准时间无关,要用也只能用来比如计算方法执行时间等。2、这个值的起始时间不是笃定的。3、不同虚拟机下边获取这个时间可能还不同。)This method provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes) - no guarantees are made except that the resolution is at least as good as that of currentTimeMillis().
此方法提供纳秒精度,但不一定是纳秒分辨率(即值更改的频率)-除了分辨率至少与currentTimeMillis()一样好之外,没有任何保证。Differences in successive calls that span greater than approximately 292 years (263 nanoseconds) will not correctly compute elapsed time due to numerical overflow.
由于数值溢出,跨度超过约292年(263纳秒)的连续调用之间的差异将无法正确计算所用时间。The values returned by this method become meaningful only when the difference between two such values, obtained within the same instance of a Java virtual machine, is computed.
只有当计算在Java虚拟机的同一实例中获得的两个这样的值之间的差时,此方法返回的值才有意义。

怎么计算得来的,看下懂C的人分析:JVM源码分析之System.currentTimeMillis及nanoTime原理详解

里边有句重点:

我们JVM里取纳秒数时传入的是CLOCK_MONOTONIC这个参数,因此会调用如下的方法

上面的wall_to_monotonic的tv_sec以及tv_nsec都是负数,在系统启动初始化的时候设置,记录了启动的时间。因此nanoTime其实算出来的是一个相对的时间,相对于系统启动的时候的时间。 

而System.currentTimeMillis()是返回的当前时间距离1970/01/01 08:00:00的毫秒数。

GO time.Now().UnixNano()

time.Now().UnixNano()

执行结果:1681209667509687900,结果与JAVA的获取纳秒时间相差太多。看GO的源码注释:

// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
// since January 1, 1970 UTC. The result is undefined if the Unix time
// in nanoseconds cannot be represented by an int64 (a date before the year
// 1678 or after 2262). Note that this means the result of calling UnixNano
// on the zero Time is undefined. The result does not depend on the
// location associated with t.
func (t Time) UnixNano() int64 {return (t.unixSec())*1e9 + int64(t.nsec())
}

重点就是这句:UnixNano返回t作为Unix时间,即自1970年1月1日UTC以来经过的纳秒数。

这个就是GO与JAVA(nanoTime其实算出来的是一个相对的时间,相对于系统启动的时候的时间。 )区别太大的原因。

如何使用JAVA计算与GO相同的纳秒呢?可以留言讨论。。。