Система.currentTimeMillis против системы.nanoTime

Точность Vs. Точность

что я хотел бы знать, должен ли я использовать

10 ответов


если вы просто ищете чрезвычайно точные измерения времени используйте System.nanoTime(). System.currentTimeMillis() даст вам наиболее точное возможное время, прошедшее в миллисекундах с эпохи, но System.nanoTime() дает вам наносекундное точное время относительно некоторой произвольной точки.

из документации Java:

public static long nanoTime()

возвращает текущее значение наиболее точного системного таймера в наносекундах.

этот метод можно использовать только для измерять прошедшее время и нет связано с любым другим понятием системы или настенные часы. Возвращаемое значение представляет наносекунды с некоторым фиксированное, но произвольное время (возможно, в будущее, поэтому ценности могут быть негативный.) Этот метод обеспечивает наносекундная точность, но не обязательно наносекундная точность. Нет гарантии сделаны о том, как часто значения меняются. Различия в последовательных вызовах, которые охватывают больше чем около 292 лет (263 наносекунды) будет не точно вычислить прошедшее время из-за численного переполнение.

например, чтобы измерить, сколько времени занимает выполнение некоторого кода:

long startTime = System.nanoTime();    
// ... the code being measured ...    
long estimatedTime = System.nanoTime() - startTime;

Читайте также: Система JavaDoc.nanoTime() и Система JavaDoc.currentTimeMillis() для получения дополнительной информации.


Потокобезопасность

поскольку никто больше не упоминал об этом...

Не Безопасно

это не безопасно сравнивать результаты System.nanoTime() вызовы между различными потоками. Даже если события потоков происходят в предсказуемом порядке, разница в наносекундах может быть положительной или отрицательной.

безопасное

System.currentTimeMillis() безопасно для использования между потоками.


обновление Аркадий: Я наблюдал более правильное поведение System.currentTimeMillis() в Windows 7 в Oracle Java 8. Время было возвращено с точностью до миллисекунды. Исходный код в OpenJDK не изменился, поэтому я не знаю, что вызывает лучшее поведение.


Дэвид Холмс из Sun опубликовал статью в блоге пару лет назад, которая имеет очень подробный взгляд на API синхронизации Java (в частности System.currentTimeMillis() и System.nanoTime()), когда вы хотите использовать, и как они работать внутренне.

внутри Hotspot VM: часы, таймеры и планирование событий-Часть I-Windows

один очень интересный аспект таймера, используемого Java в Windows для API, которые имеют параметр timed wait, заключается в том, что разрешение таймера может изменяться в зависимости от того, какие другие вызовы API могут быть сделаны - в масштабах всей системы (а не только в конкретном процессе). Он показывает пример использования Thread.sleep() вызовет это изменение разрешения.


System.nanoTime() не поддерживается в старых JVMs. Если это вызывает беспокойство, придерживайтесь currentTimeMillis

что касается точности, вы почти правильно. На некоторых машинах Windows, currentTimeMillis() имеет разрешение около 10 мс (не 50 мс). Я не уверен, почему, но некоторые машины Windows так же точны, как и машины Linux.

я использовал GAGETimer в прошлом со скромным успехом.


как говорили другие, currentTimeMillis-это время часов, которое изменяется из-за летнего времени, пользователей, изменяющих настройки времени, високосных секунд и синхронизации времени в интернете. Если ваше приложение зависит от монотонно возрастающих значений прошедшего времени,вы можете предпочесть nanoTime.

вы можете подумать, что игроки не будут возиться с настройками времени во время игры, и, возможно, вы будете правы. Но не стоит недооценивать нарушение из - за синхронизации времени в интернете, или, возможно пользователи удаленных рабочих столов. API nanoTime невосприимчив к такого рода нарушениям.

Если вы хотите использовать тактовое время, но избежать прерываний из-за синхронизации времени в интернете, вы можете рассмотреть клиент NTP, такой как Майнберг, который "настраивает" тактовую частоту до нуля, а не просто периодически сбрасывает часы.

Я говорю Из личного опыта. В приложении погоды, которое я разработал, я получал случайные всплески скорости ветра. Мне потребовалось время, чтобы поймите, что моя временная база была нарушена поведением часов на типичном ПК. Все мои проблемы исчезли, когда я начал использовать nanoTime. Последовательность (монотонность) была более важна для моего приложения, чем сырая точность или абсолютная точность.


да, если такая точность требуется использовать System.nanoTime(), но имейте в виду, что вам требуется Java 5+ JVM.

в моих системах XP я вижу, что системное время сообщается по крайней мере 100 микросекунд 278 наносекунд использовать следующий код:

private void test() {
    System.out.println("currentTimeMillis: "+System.currentTimeMillis());
    System.out.println("nanoTime         : "+System.nanoTime());
    System.out.println();

    testNano(false);                                                            // to sync with currentTimeMillis() timer tick
    for(int xa=0; xa<10; xa++) {
        testNano(true);
        }
    }

private void testNano(boolean shw) {
    long strMS=System.currentTimeMillis();
    long strNS=System.nanoTime();
    long curMS;
    while((curMS=System.currentTimeMillis()) == strMS) {
        if(shw) { System.out.println("Nano: "+(System.nanoTime()-strNS)); }
        }
    if(shw) { System.out.println("Nano: "+(System.nanoTime()-strNS)+", Milli: "+(curMS-strMS)); }
    }

У меня был хороший опыт работы с nanotime. Он обеспечивает время настенных часов как два длинных (секунды с эпохи и наносекунды в течение этой секунды), используя библиотеку JNI. Он доступен с предварительно скомпилированной частью JNI для Windows и Linux.


для игровой графики и гладких обновлений позиций используйте System.nanoTime(), а не System.currentTimeMillis(). Я переключился с currentTimeMillis() на nanoTime () в игре и получил значительное визуальное улучшение плавности движения.

хотя одна миллисекунда может показаться, что она уже должна быть точной, визуально это не так. Факторы nanoTime() может улучшить включают в себя:

  • точное позиционирование пикселей ниже разрешения настенных часов
  • возможность анти-псевдонима между пикселями, если вы хотите
  • окна настенные часы неточность
  • дрожание часов (несоответствие, когда настенные часы фактически тикают вперед)

как показывают другие ответы, nanoTime имеет стоимость производительности при повторном вызове - было бы лучше вызвать его только один раз за кадр и использовать то же значение для расчета всего кадра.


System.currentTimeMillis() небезопасно для истекшего времени, потому что этот метод чувствителен к системным изменениям часов реального времени системы. Вы должны использовать System.nanoTime. Обратитесь к справке по системе Java:

о методе nanoTime:

.. Этот метод обеспечивает наносекундную точность, но не обязательно разрешение наносекунды (то есть, как часто изменяется значение) - нет гарантии, за исключением того, что разрешение как минимум не хуже что currentTimeMillis()..

Если вы используете System.currentTimeMillis() прошедшее время может быть отрицательным (назад


одна вещь здесь-несоответствие метода nanoTime.он не дает очень последовательных значений для одного и того же ввода.currentTimeMillis делает намного лучше с точки зрения производительности и согласованности,а также ,хотя и не так точно,как nanoTime,имеет меньший предел погрешности, а следовательно, и большую точность в его значении. поэтому я предлагаю вам использовать currentTimeMillis