Java计时,System.nanoTime()比System.currentTimeMillis()更好,但它在睡眠期间是否持续?

4

我正在尝试实现一个计时器,它可以用于短时间 (秒) 和长时间 (小时等) 的事件。

理想情况下,它应该在 CPU 关闭的时候保留,例如电池已经耗尽。如果我使用 System.currentTimeMillis() 设置开始时间和结束时间,它在几乎所有情况下都有效,除了像闰秒、闰年、夏令时变化等时期...或者,如果用户只是改变时间 (我已经验证过这一点)。顺便说一句,这是在 Android 系统上。

相反,如果我使用 System.nanoTime(),除了可能更精确外,它不会出现通常与时间更改等有关的“硬性问题”。我的问题是,System.nanoTime() 是否从某个任意时间开始测量纳秒?我不确定正确的术语是什么,但是例如,如果在 X 处运行 System.nanoTime(),然后 X + 1 小时后关闭系统 (例如 Android 设备上的电池已耗尽),然后再过 10 小时,系统重新启动,此时运行 System.nanoTime(),它会返回 10 个小时吗?还是会返回 1 小时(因为当系统处于关闭/睡眠状态时,nanoTime 使用的“计数器”可能没有运行)?


“它不会像通常那样遇到时间变化的问题”,我不明白你为什么这么认为。所有绝对时间度量都需要由更高级别的API进行解释,以准确地转换为人类时间,考虑到夏令时等因素。 - Affe
我的意思是,我不关心绝对时间的时间核算。我只关心经过的时间。这个应用程序将像一个烹饪计时器一样使用。如果用户在计时器启动和停止之间重新启动、关闭、调整时钟等,计时器仍应该正常工作。 - Tony Tieger
似乎nanoTime()允许用户调整时钟并仍然工作,但不适用于重新启动/关闭,而currentTimeMillis适用于重新启动/关闭,但不适用于用户调整时钟。真的希望nanoTime()能够工作,因为nanoTime的定义是来自任意起始时间,希望这个起始时间在一台机器上是恒定的,并且在机器重新启动等情况下不会改变... - Tony Tieger
2个回答

2

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

我认为您无法在Android中测量关闭时间。

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


啊,是的,我看过了,它看起来是一个不错的解决方案。nanoTime()会更准确吗?elapsedRealtime()似乎类似于nanoTime(),除了毫秒与纳秒精度之外,而且elapsedRealtime()有一个设置起始参考点(系统启动)与任意起始参考点的区别。 - Tony Tieger
2
从这里看(http://comments.gmane.org/gmane.comp.handhelds.android.platform/6874),System.nanoTime()使用CLOCK_MONOTONIC的clock_gettime()。当设备进入深度睡眠时,该时钟会停止,因此nanoTime()无法工作。我认为elapsedRealtime()是最佳解决方案,因为它只有在系统关闭时才不能正常工作。我将使用这个方法,谢谢! - Tony Tieger

1

未定义

"返回的值表示自某个固定但任意的起始时间以来的纳秒数(可能是在未来,因此值可能为负)。所有Java虚拟机实例中的此方法的调用都使用相同的起点;其他虚拟机实例可能使用不同的起点。"

为简单起见,我们假设当您在时间X运行它时,原点是X(这是允许的)。这意味着它将返回0,而在VM实例内,时间将以与普通时钟相同的速率流逝。

当您使用Thread.sleep时,它不会更改VM实例,因此不会被特殊处理。

但是,在设备重新启动后,您将进入另一个VM实例。因此,不能保证X仍然是原点。


啊,谢谢,这样它就不会在机器关机后持续存在了。这个计时函数的目的是计算任何东西的时间,从开始到结束。在开始和结束之间发生什么事情没有保证(用户理论上可以重新启动机器,关闭机器一小时,将系统时钟提前一小时等等)。 - Tony Tieger

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