Java System.nanoTime() 与 System.currentTimeMillis
Java提供了两种计时操作方法,System.nanoTime() 和 System.currentTimeMillis()。但是在什么情况下应该使用哪一个呢?哪个更有效率?
乍一看,似乎应该使用 nanoTime(),因为它给出了更精确的时间值(以纳秒为单位,与其他方法返回的毫秒相比)。但是使用 nanoTime 在 CPU 上总是有效的吗?让我们看看使用这两种方法的优缺点:
System.currentTimeMillis()
public static long currentTimeMillis()
// Returns the current time in milliseconds.
优点:
- 它是线程安全的。线程安全意味着如果在两个或多个不同的线程之间调用这个方法,它不会返回错误的结果。
- 始终返回自纪元以来经过的绝对时间(自 1970 年 1 月 1 日 00:00 以来的毫秒数)。
- 消耗更少的时钟周期来执行(大约 5-6 个 cpu 时钟)。
- 给出更准确的时间,因为参考点(纪元)是固定的。
缺点:
- 不太精确。结果在 1/1000 到 15/1000 秒之间。在某些机器上,分辨率甚至低于 50 毫秒,最多只能达到 10 毫秒。
- 如果用户更改系统时间、达到闰秒或 NTP 同步发生更改,则可能会给出错误的结果。
System.nanoTime()
public static long nanoTime()
// Returns the current value of the running JVM's high-resolution
// time source, in nanoseconds.
优点:
- 高度精确。返回的时间约为 1/1000000 秒。
- 分辨率远高于currentTimeMillis() 。
缺点:
- 反映的结果没有任何固定的参考点。根据Java文档,
The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values may be negative).
- 不太准确。此方法提供纳秒精度,但不一定提供纳秒精度。不保证值的变化频率。
- 根据系统的不同,执行可能需要超过 100 个 cpu 周期。
- 不是线程安全的。如果在多个线程之间使用,可能会返回错误结果。
让我们看一个工作示例来比较这两个函数的结果:
// Java program to illustrate
// difference between
// Java System.nanoTime()
// and System.currentTimeMillis
class Main {
public static void main(String[] args)
{
// Get the current system time in
// both nano and milli-seconds before
// calling the function.
long nano_startTime = System.nanoTime();
long millis_startTime = System.currentTimeMillis();
// Perform the work whose time is to be measured
someFunction();
// Get the current system time in both
// nano and milli-seconds after
// the function returns.
long nano_endTime = System.nanoTime();
long millis_endTime = System.currentTimeMillis();
// Print the time taken by subtracting
// the end-time from the start-time
System.out.println("Time taken in nano seconds: "
+ (nano_endTime - nano_startTime));
System.out.println("Time taken in milli seconds: "
+ (millis_endTime - millis_startTime));
}
// The function whose execution
// time is to be measured
public static void someFunction()
{
for (int i = 0; i < Integer.MAX_VALUE; i++) {
for (int j = 0; j < Integer.MAX_VALUE; j++) {
// Here for example purpose
// we run an empty loop
}
}
}
}
输出:
Time taken in nano seconds: 2519657
Time taken in milli seconds: 3
总之,只要要执行高精度任务,就可以/必须使用 System.nanoTime() ,因为毫秒似乎足够精确,但对于需要快速性能的应用程序(如游戏)nanoTime() 会提供更好的效果结果。
但是,由于计算开销和与线程安全相关的风险,应尽可能避免使用,在这种情况下将使用 currentTimeMillis()。