📜  Java System.nanoTime() 与 System.currentTimeMillis

📅  最后修改于: 2022-05-13 01:55:47.762000             🧑  作者: Mango

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.

优点:

  1. 它是线程安全的。线程安全意味着如果在两个或多个不同的线程之间调用这个方法,它不会返回错误的结果。
  2. 始终返回自纪元以来经过的绝对时间(自 1970 年 1 月 1 日 00:00 以来的毫秒数)。
  3. 消耗更少的时钟周期来执行(大约 5-6 个 cpu 时钟)。
  4. 给出更准确的时间,因为参考点(纪元)是固定的。

缺点:

  1. 不太精确。结果在 1/1000 到 15/1000 秒之间。在某些机器上,分辨率甚至低于 50 毫秒,最多只能达到 10 毫秒。
  2. 如果用户更改系统时间、达到闰秒或 NTP 同步发生更改,则可能会给出错误的结果。

System.nanoTime()

public static long nanoTime()
// Returns the current value of the running JVM's high-resolution
// time source, in nanoseconds.

优点:

  1. 高度精确。返回的时间约为 1/1000000 秒。
  2. 分辨率远高于currentTimeMillis()

缺点:

  1. 反映的结果没有任何固定的参考点。根据Java文档,
    The value returned represents nanoseconds since some fixed
    but arbitrary time (perhaps in the future, so values may be negative).
  2. 不太准确。此方法提供纳秒精度,但不一定提供纳秒精度。不保证值的变化频率。
  3. 根据系统的不同,执行可能需要超过 100 个 cpu 周期。
  4. 不是线程安全的。如果在多个线程之间使用,可能会返回错误结果。

让我们看一个工作示例来比较这两个函数的结果:

// 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()。