System.nanoTime() против System.currentTimeMillis()
Java предоставляет два метода для определения времени операций: System.nanoTime () и System.currentTimeMillis (). Но какой из них следует использовать в каких условиях? И что более эффективно?
На первый взгляд может показаться, что следует использовать nanoTime (), поскольку он дает более точное значение времени (в нано секундах по сравнению с миллисекундами, которые возвращает другой метод). Но всегда ли эффективно на процессоре использовать nanoTime? Давайте посмотрим на плюсы и минусы использования обоих методов:
System.currentTimeMillis ()
public static long currentTimeMillis ()
// Возвращает текущее время в миллисекундах.
Плюсы:
Это потокобезопасно . Потоковая безопасность означает, что если этот метод вызывается между двумя или более различными потоками, он не будет возвращать ошибочные результаты.
Всегда возвращает абсолютное время, прошедшее с начала эпохи (число в миллис с 1 января 1970 г. 00:00).
Потребляет меньше тактов для выполнения (около 5-6 тактовых процессоров).
Дает более точное время, так как точка отсчета (эпоха) является фиксированной.
Минусы:
Менее точный . Результат где-то между 1/1000-й / 15/1000-й секунды. На некоторых машинах разрешение даже меньше 50 мс и может снизиться только до 10 мс.
Это может дать неправильные результаты, если пользователь изменяет системное время, делает скачок в секунду или происходят изменения в синхронизации NTP.
System.nanoTime ()
public static long nanoTime ()
// Возвращает текущее значение высокого разрешения работающей JVM
// источник времени, в наносекундах.
Плюсы:
Очень точный . Возвращенное время составляет около 1/1000000-й секунды.
Разрешение намного выше, чем currentTimeMillis () .
Минусы:
Отраженный результат не имеет фиксированной контрольной точки. Согласно документации Java,
Возвращаемое значение представляет наносекунды, так как некоторые фиксированные
но произвольное время (возможно, в будущем, поэтому значения могут быть отрицательными).
В зависимости от системы может потребоваться более 100 циклов процессора.
Не потокобезопасен . Может возвращать ошибочные результаты, если используется между несколькими потоками.
Давайте посмотрим на рабочий пример, чтобы сравнить результаты этих двух функций:
class Main {
public static void main(String[] args)
{
long nano_startTime = System.nanoTime();
long millis_startTime = System.currentTimeMillis();
// Perform the work whose time is to be measured
someFunction();
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
}
}
}
}
Вывод:
Время в нано секундах: 2519657
Время в миллисекундах: 3
В заключение:
System.nanoTime () можно / нужно использовать всякий раз, когда должны выполняться задачи с высокой точностью , потому что может показаться, что миллисекунд достаточно, но для приложений, требующих высокой производительности (таких как игры), nanoTime () даст намного лучше полученные результаты.
Однако, по возможности, его следует избегать из-за вычислительных затрат и рисков, связанных с безопасностью потоков, и в этом случае следует использовать currentTimeMillis ().