System.nanoTime()的精度与准确度

and*_*sdr 24 java nanotime

文件System.nanoTime()说明如下(强调我的).

此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关.返回的值表示纳秒,因为某些固定但是任意时间(可能在将来,因此值可能为负).该方法提供纳秒精度,但不一定是纳秒精度.不保证值的变化频率.

在我看来,这可以用两种不同的方式解释:

  1. 上面粗体的句子是指个人返回值.然后,从数值意义上理解精度和准确度.也就是说,精度指的是有效数字的数量 - 截断的位置,精确度是指数字是否正确(如前面的答案 中所述,'精确'和'准确度'之间有什么区别?)

  2. 上面粗体的句子指的是方法本身的能力.然后,精确度和准确性将被理解为飞镖类比(http://en.wikipedia.org/wiki/Precision_vs._accuracy#Accuracy_versus_precision:_the_target_analogy).因此,低精度,高精度=>错误的值被高精度地反复击中:想象物理时间静止不动,nanoTime()的连续调用返回相同的数值,但是它与实际经过的时间有关.参考时间通过一些常数偏移.

哪种解释是正确的?我的观点是,解释2意味着使用nanoTime()(通过减去两个返回值)测量时间将是正确的纳秒(因为测量中的常数误差/偏移将被消除),而解释1将不会不能保证测量之间的一致性,因此不一定意味着高精度的时间差测量.


2013年 4月15日更新: Java 7文档System.nanoTime()已更新,以解决可能与以前的措辞混淆.

返回正在运行的Java虚拟机的高分辨率时间源的当前值,以纳秒为单位.

此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关.返回的值表示纳秒,因为某些固定但任意的原始时间(可能在将来,因此值可能为负).在Java虚拟机的实例中,此方法的所有调用都使用相同的原点; 其他虚拟机实例可能使用不同的来源.

这种方法提供纳秒级精度,但不一定是纳秒级分辨率(即,值的变化频率) - 除了分辨率至少与分辨率一样好之外,不做任何保证currentTimeMillis().

跨越大于约292年(2 63纳秒)的连续调用的差异将无法正确计算由于数值溢出而导致的经过时间.

仅当计算在Java虚拟机的同一实例中获得的两个此类值之间的差异时,此方法返回的值才有意义.

Joo*_*kka 12

在Clojure命令行中,我得到:

user=> (- (System/nanoTime) (System/nanoTime))
0
user=> (- (System/nanoTime) (System/nanoTime))
0
user=> (- (System/nanoTime) (System/nanoTime))
-641
user=> (- (System/nanoTime) (System/nanoTime))
0
user=> (- (System/nanoTime) (System/nanoTime))
-642
user=> (- (System/nanoTime) (System/nanoTime))
-641
user=> (- (System/nanoTime) (System/nanoTime))
-641
Run Code Online (Sandbox Code Playgroud)

从本质nanoTime上讲,每一纳秒都不会更新,这与人们对其精确度的直观预期相反.在Windows系统中,它使用了QueryPerformanceCounter引擎盖下的 API(根据本文),实际上它似乎提供了大约640 ns的分辨率(在我的系统中!).

注意,nanoTime它本身不能具有任何准确性,因为它的绝对值是任意的.只有 连续调用之间的差异nanoTime才有意义.该差异的(in)准确度在1微秒的范围内.

  • 很好的答案,这是事实.我认为这里的重要部分是Java人员意识到操作系统的"时钟"时间(来自芯片和操作系统缓存)存在各种问题,从漂移到精度和延迟(在各种系统上每隔+/- 30毫秒更新一次).所以这个"nanoTime"的实现真的很不一样 - 不是使用时钟芯片而是使用"高性能定时器"实现,它在操作系统级别上有所不同,但结果是相同的 - 分辨率比旧的+/-更精确的定时器30 ms缓存/漂移. (2认同)

Mar*_*nik 10

第一种解释是正确的.在大多数系统中,三个最低有效数字始终为零.这实际上提供了微秒精度,但是以纳秒的固定精度水平报告.

事实上,现在我再次看一遍,你的第二个解释也是对正在发生的事情的有效描述,甚至更多.想象冻结时间,报告将始终是相同的错误纳秒数,但如果理解为整数微秒,则更正.


小智 5

System.currentTimeMillis()&之间的区别的一个非常有趣的特征System.nanoTime()是它System.nanoTime()不会随挂钟而改变。我在具有严重时间漂移的 Windows 虚拟机上运行代码。System.currentTimeMillis()当 NTP 纠正这种漂移时,每次可以向后或向前跳 1-2 秒,从而使准确的时间戳变得毫无意义。(Windows 2003、2008 VPS 版本)

System.nanoTime()但是,它不会受到更改挂钟时间的影响,因此您可以通过 NTP 检索时间,并根据上次检查 NTP 进行修正,这样您就可以获得比不利挂钟条件下System.nanoTime()更准确的时间System.currentTimeMillis()

这当然是违反直觉的,但了解一下很有用