System.currenTimeInMillis()和System.nanoTime()的区别

25

我知道System.nanoTime()现在是测量时间的首选方法,而不是System.currentTimeInMillis()。第一个显而易见的原因是nanoTime()提供更精确的时间,我阅读过的另一个原因是后者会受到系统实时时钟调整的影响。那么"受到系统实时时钟调整的影响"是什么意思?


我也很好奇。如果在夏令时转变期间尝试使用currentTimeInMillis()记录经过的时间,会发生什么?或者这不是它的意思吗? - telkins
3
currentTimeMillis 试图测量的是时间作为一个物理现象的流逝。夏令时调整类似于旅行中的时区变化:它只影响时间以小时和分钟表示的方式,而时间本身并未受到影响。 - Joni
2
currentTimeMillis 不受 DST 的影响,但受闰秒等因素的影响,而 nanoTime 则不同。 - Louis Wasserman
@LouisWasserman在platzhirsch的回答提到的博客中写道:“这是一个问题,因为与绝对时间相关的事件需要意识到绝对时间的变化(例如夏令时的开始/结束),而相对时间应该免受这些变化的影响。不可避免地,这意味着大多数操作系统都存在问题(或者是这样或者是那样)。”由于currentTimeInMillis使用“当天的时间”或绝对时钟,这是否意味着currentTimeInMillis会受到DST的影响? - Geek
1
@JoniSalonen,请看一下我对Louis的评论。你对此有什么看法? - Geek
1
currentTimeMillis测量自1970年1月1日00:00 UTC以来经过的时间。在DST转换中发生的情况是调整挂钟时间:例如,在00:59:59之后的一秒钟,挂钟时间为02:00:00。但由于只有一秒钟过去了,因此currentTimeMillis的值应该仅增加一秒钟,而不是增加一小时一秒钟。 - Joni
3个回答

27
在这种情况下,我发现以下博客文章摘录很有用:
如果您有兴趣测量绝对时间,请始终使用System.currentTimeMillis()。请注意,它的分辨率可能相当粗糙(尽管这很少成为绝对时间的问题)。
如果您有兴趣测量/计算经过的时间,请始终使用System.nanoTime()。在大多数系统上,它将提供微秒级别的分辨率。但是,请注意,此调用在某些平台上执行也可能需要微秒级别的时间。
由David Holmes撰写的时钟和计时器-总体概述
由于System.currentTimeMillis()依赖于系统的日历时间时钟,因此对时间进行调整是合法的,以使其保持准确。
这里的调整意味着什么?例如,看一下Linux中CLOCK_REALTIME的描述:
系统范围内的时钟可以测量真实(即挂钟)时间。设置此时钟需要适当的权限。该时钟受到系统时间不连续跳跃(例如,如果系统管理员手动更改时钟)和 adjtime(3)和 NTP 执行的增量调整的影响。

这是您提供的链接中的内容:“相对时间时钟由System.nanoTime()方法表示,该方法返回以纳秒为单位的“自由运行”时间。” 为什么它被称为“自由运行”时间? - Geek
@Geek 我会说是自由的,意思是独立的。绝对时间取决于操作系统触发的中断。相对的自由运行时间是独立于此的,并且正如Joni Salonen所指出的那样,是从内部CPU时钟计时器派生出来的。 - Konrad Reiche
系统通常具有绝对时钟(即日历时钟,分辨率较低)和相对时钟(某种“高分辨率”计数器,可从中计算出“自由运行”时间)。为什么日历时钟具有低分辨率,而相对时钟具有高分辨率? - Geek
例如,CPU时间戳计数器(http://en.wikipedia.org/wiki/Time_Stamp_Counter)更加精确,因为它大致上在每个内部处理器时钟周期后递增。重复中断信号的频率要低得多。 - Konrad Reiche

8

只需查看方法的JavaDoc:

System.nanoTime()

"...此方法仅用于测量经过的时间,与任何其他系统或墙钟时间概念无关。..."

System.currentTimeMillis()

"...以毫秒为单位返回当前时间。..."

因此,如您所见,如果在使用System.currentTimeMillis()进行测量期间系统时间发生更改,则您测量的间隔也将发生更改。但是,使用System.nanoTime()方法测量间隔时不会更改。


6
这意味着System.currentTimeMillis()返回的值来自机器的内部时钟。如果系统管理员(或NTP)更改了时间,例如发现时钟快了5分钟并进行更正,那么System.currentTimeMillis()将受到影响。这意味着您甚至可能会看到该值减少,如果您用它来测量时间间隔,则计时可能会出错。您甚至可能会测量到计时。
另一方面,System.nanoTime()返回的值是从某些内部CPU计数器/时钟派生的。由此时钟测量的时间不会被任何用户或程序更改。这意味着它在计时方面更可靠。但是,CPU时钟在断电时会重置,因此它对于查找当前的“墙钟”时间没有用处。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接