三种不同的时钟是适合的,并且他们不应该被混淆:
System.currentTimeMillis()是一个标准的“墙”时钟(时间和日期)表达毫秒自纪元。该墙时钟能够被用户或电话网络(见setCurrentTimeMillis(long))设置,所以时间可能会向前或向后不可预知地跳。该时钟应该仅仅被使用,当现实世界的对应的日期和时间是重要的,例如在一个日历或闹钟应用程序。间隔的或经过的时间测量应该使用一个不同的时钟。如果你使用System.currentTimeMillis(),考虑监听 ACTION_TIME_TICK
,ACTION_TIME_CHANGED
和 ACTION_TIMEZONE_CHANGED
意图广播去发现当时间变化的时候。
uptimeMillis()以毫秒为单位进行计数自系统启动时。该时钟停止当系统进入深度睡眠时(CPU关闭,显示黑暗,等待外部输入装置),但是不被时钟调整,闲置或其他节能机制影响。 这是基本的对于大多数时间间隔例如Thread.sleep(millls)
,
Object.wait(millis)
,和 System.nanoTime()
。
该时钟被保证是单调的,并且是为通用的用户界面事件,性能测量,和其他任何不需要在器件测量经过睡眠时间间隔时间的建议的基础。大多数的方法接受一个时间戳的值除了uptimeMillis()时钟。
elapsedRealtime()以毫秒为单位进行计数自动系统启动,包含深度睡眠。该时钟应该被使用当测量时间间隔可能跨越系统睡眠的时间段。
这有一些机制为了控制定时事件的:
标准的功能像 Thread.sleep(millis)
和 Object.wait(millis)
都总是合适的。这是功能使用uptimeMillis()时钟;如果该设备进入睡眠,剩余的时间将被推迟直到系统唤醒。这些同步功能可能被中断伴随 Thread.interrupt()
方法,并且你必须处理InterruptedException异常。
SystemClock.sleep(millis) 是一种实用工具函数变化类似于Thread.sleep(millis)
,
但是它忽视了InterruptedException异常。使用该函数产生的延迟如果你不使用Thread.interrupt(),因为它会保存线程的中断状态。
处理程序类可以安排在绝对或相对时间异步回调。处理器类对象也使用 uptimeMillis()
时钟,并且需要一个event loop(正常呈现在任何一个GUI应用程序上)。该AlarmManager可以触发一次或重复事件去发生即使在深睡眠或你的应用程序没有运行。事件可能有计划的发生伴随你的 currentTimeMillis()(RTC)
机会或 elapsedRealtime()
(ELAPSED_REALTIME),并且引起一个意图广播当它们发生时。
在Andriod中关于线程一部分中经常会遇到计算时间的操作,这里面应用较多的是SystemClock类,这个类有两个主要的静态方法uptimeMillis()和 elapsedRealtime().
我们来看一下这两个函数的实际含义,以下是源码中的注释
Returns milliseconds since boot, not counting time spent in deep sleep.
This value may get reset occasionally
native public static long uptimeMillis();
Returns milliseconds since boot, including time spent in sleep.
native public static long elapsedRealtime();
由此可见,uptimeMillis()返回的是系统从启动到当前处于非休眠期的时间。
elapsedRealTime()返回的是系统从启动到现在的时间。
值得一提的是,这个类还提供了另外一个方法, public static void sleep(long ms),这个方法就是封装了Thread.sleep方法,但是不会抛出InterruptedException