25

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

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

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

  1. 上面粗体是指单独的返回值。然后,精度和准确度要从数字的意义上来理解。也就是说,精度是指有效数字的个数——截断的位置,而精度是数字是否正确(比如这里的顶部答案中描述的 'precision'和'accuracy'有什么区别?

  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 虚拟机的同一实例中获得的两个此类值之间的差异时,此方法返回的值才有意义。

4

4 回答 4

12

In Clojure command line, I get:

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

So essentially, nanoTime doesn't get updated every nanosecond, contrary to what one might intuitively expect from its precision. In Windows systems, it's using the QueryPerformanceCounter API under the hood (according to this article), which in practice seems to give about 640 ns resolution (in my system!).

Note that nanoTime can't, by itself, have any accuracy at all, since its absolute value is arbitrary. Only the difference between successive nanoTime calls is meaningful. The (in)accuracy of that difference is in the ballpark of 1 microsecond.

于 2012-07-12T13:56:36.123 回答
10

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

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

于 2012-07-12T13:36:09.197 回答
4

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

System.nanoTime()但是,不受更改挂钟时间的影响,因此您可以通过 NTP 检索时间并根据System.nanoTime()上次检查 NTP 后应用校正,并且您的时间比System.currentTimeMillis()不利的挂钟条件更准确

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

于 2013-09-12T09:30:52.730 回答
2

如果像我这样的人来一次又一次阅读这个问题仍然有点理解它,这里有一个更简单(我希望)的解释。

Precision是关于您保留多少位数。每个:

long start = System.nanoTime();
long end   = System.nanoTime();

将是一个精确的数字(很多数字)。

由于accuracy与 something 比较来衡量,因此单独调用 toSystem.nanoTime没有任何意义,因为它的值是非常任意的,并且不依赖于我们可以衡量的东西。区分其准确性的唯一方法是对其进行两次不同的调用,因此:

 long howMuch = end - start;

不会有纳秒的精度。事实上,在我的机器上,差异是 0.2 - 0.3 微秒。

于 2018-02-15T20:34:21.113 回答