Java 计时,System.nanoTime() 比 System.currentTimeMillis() 更胜一筹,但它会在睡眠期间持续存在吗?

Posted

技术标签:

【中文标题】Java 计时,System.nanoTime() 比 System.currentTimeMillis() 更胜一筹,但它会在睡眠期间持续存在吗?【英文标题】:Java timing, System.nanoTime() batter than System.currentTimeMillis() but does it persist over sleep? 【发布时间】:2012-06-18 22:09:43 【问题描述】:

我正在尝试实现一个计时器,它可能用于短(秒)事件或更长(小时等)事件。

理想情况下,它应该在 CPU 关闭的一段时间内持续存在,例如,电池没电了。如果我使用 System.currentTimeMillis() 设置开始时间并使用相同的函数设置结束时间,它几乎适用于所有情况,除了在闰秒、闰年、夏令时更改等期间...或者,如果用户只是更改时间(我已经验证了这一点)。顺便说一句,这是在 android 系统上。

相反,如果我使用 System.nanoTime(),除了可能更准确之外,它不会出现时间变化等常见的“困难时间”问题。我的问题是,System.nanoTime()在“困难时期”从某个任意时间测量纳秒?我不确定正确的术语是什么,但例如,System.nanoTime() 会在 X 处运行,然后 X+1 小时后,系统关闭(例如,Android 设备上的电池没电了),然后是 X +10 小时,系统启动,此时运行 System.nanoTime() 会返回 10 小时吗?或者它会返回 1 小时(因为 nanoTime 使用的“计数器”在系统关闭/休眠时可能不会运行?)。

【问题讨论】:

“它不会有通常的“困难时间”问题随着时间的变化,”不明白你为什么这么认为。所有绝对时间度量都需要更高级别的 API 进行解释,才能准确地转化为人类时间,以考虑夏令时等因素。 我的意思是,我不关心绝对时间的时间计算。我只关心经过的时间。此应用程序将用作烹饪计时器。如果用户在定时器的启动和停止之间重启、关闭、调整时钟等,定时器应该仍然工作。 似乎 nanoTime() 将允许用户调整时钟并且仍然可以工作,但不适用于重启/关机,而 currentTimeMillis 将适用于重启/关机,但不适用于用户调整时钟。真的希望 nanoTime() 能工作,因为 nanoTime 的定义说它来自任意的起始时间,希望这个起始时间在一台机器上是恒定的,并且在机器重新启动时不会改变,等等...... 【参考方案1】:

android.os.SystemClock.elapsedRealtime() - 自系统启动以来的毫秒数,包括处于睡眠状态的时间。这应该是你最好的选择。

我不认为你可以在 android 中测量关机时间。

要了解更多信息,最好查看 android 系统时钟页面。 http://developer.android.com/reference/android/os/SystemClock.html

【讨论】:

啊,是的,我已经看过了,它看起来是一个很好的解决方案。 nanoTime() 会更准确吗?似乎 elapsedRealtime() 类似于 nanoTime(),除了毫微精度和纳米精度之外,并且 elapsedRealtime() 具有设置的启动参考(系统启动)与任意启动参考。 从这里:comments.gmane.org/gmane.comp.handhelds.android.platform/6874 似乎 System.nanoTime() 使用 clock_gettime() 和 CLOCK_MONOTONIC。当设备进入深度睡眠时时钟停止,因此 nanoTime() 将不起作用。我认为 elapsedRealtime() 是最好的解决方案,因为它仅在系统关闭时才起作用。我最终会使用这个,谢谢!【参考方案2】:

它is undefined:

"返回的值代表纳秒,因为一些固定但 任意起源时间(可能在未来,所以值可能是 消极的)。此方法的所有调用都使用相同的来源 在 Java 虚拟机的实例中;其他虚拟机 实例可能使用不同的来源。”

为简单起见,我们会说当您在时间 X 运行它时,原点是 X(这是允许的)。这意味着它将返回 0,然后在 VM 实例中,时间将以与正常时钟相同的速率流逝。

当您使用Thread.sleep 时,不会更改虚拟机实例,因此不会对其进行特殊处理。

但是,在设备重新启动后,您将处于不同的虚拟机实例中。因此,不再保证 X 是原点。

【讨论】:

啊,谢谢,所以它不会在机器关闭后持续存在。此计时功能的目的是对任何事情进行计时,从开始到停止。不保证启动和停止之间会发生什么(理论上用户可以重新启动机器、关闭机器一小时、将系统时钟提前一小时等)。

以上是关于Java 计时,System.nanoTime() 比 System.currentTimeMillis() 更胜一筹,但它会在睡眠期间持续存在吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java性能优化的十条小技巧

System.nanoTime与System.currentTimeMillis的区别

System.nanoTime()和System.currentTimeMillis()性能问题

JAVA中如何获取毫秒和微秒数

Java 计时器领域的现状如何?

System.nanoTime() 的 Java 时代? [复制]