原创

System.nanoTime()和System.currentTimeMills()的区别及使用场景

温馨提示:
本文最后更新于 2023年11月17日,已超过 432 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

日常工作中,我们经常需要用到日期函数,如获取当前时间、时间戳;而时间戳常用于计算两个操作之间的耗时统计、计算。

JDK中为我们提供了 System.currentTimeMillis()System.nanoTime() 这两个方法,两个方法都可用来统计代码耗时;但System.currentTimeMillis()还可以用来获取当前时间戳并很容易的转换为当前时间,而System.nanoTime()仅能用于统计代码更精确耗时。

System.currentTimeMillis()System.nanoTime()都是JDKrt.jar 包中System 类提供的,下面我们就JDK源码简单说一下两者的区别:

源码

System.currentTimeMillis()

 System.currentTimeMillis

从源码我们可以看到,此方法被native修饰,表明此方法由底层操作系统所提供;

我们将源码注释用翻译软件翻译出来,如下:

  • 以毫秒为单位返回当前时间。请注意,虽然返回值的时间单位是毫秒,但值的粒度取决于底层操作系统,可能更大。例如,许多操作系统以几十毫秒为单位测量时间。
  • 有关“计算机时间”和协调世界时(UTC)之间可能出现的细微差异的讨论,请参阅类日期的描述。
  • 返回:当前时间与UTC时间1970年1月1日午夜之间的时间差,以毫秒为单位。
  • 参见:java.util.Date

System.nanoTime()

System.nanoTime

此方法由底层操作系统所提供;

我们将备注翻译如下:

  • 返回正在运行的Java虚拟机的高分辨率时间源的当前值,以纳秒为单位。
  • 此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。返回的值表示从某个固定但任意的起始时间(可能在将来,因此值可能是负的)开始的纳秒数。在Java虚拟机的实例中,该方法的所有调用都使用相同的起源;其他虚拟机实例可能使用不同的源。
  • 此方法提供纳秒级精度,但不一定提供纳秒级分辨率(即值更改的频率)—除了分辨率至少与currentTimeMillis()一样好外,不能保证。
  • 如果连续调用的时间跨度超过大约292年(263纳秒),由于数值溢出,将无法正确计算经过的时间。
  • 只有当计算在Java虚拟机的同一实例中获得的两个这样的值之间的差时,这个方法返回的值才有意义。
  • 例如,要测量一些代码执行所需的时间:
    long startTime = System.nanoTime();
    / /……被测量的代码…long estimatedTime = System.nanoTime() - startTime;
    比较两个nanoTime值
    long t0 = System.nanoTime();…long t1 = System.nanoTime();
    应该使用t1 - t0 < 0,而不是t1 < t0,因为有可能出现数值溢出。
  • 返回:正在运行的Java虚拟机的高分辨率时间源的当前值,以纳秒为单位
  • 自:1.5

总结

  • 两个方法都由底层操作系统提供;
  • System.nanoTime() 只能用于测量当前虚拟机代码耗时时间;而不能用于获取当前时间或不同虚拟机之间的执行时间差;
  • System.currentTimeMillis()不仅可用于测量代码耗时,还可以正确的表示当前执行时间;
  • System.currentTimeMillis()受本地系统时间影响,所以多服务器之间需要调整一致;
正文到此结束
本文目录