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


Точность Против Точности

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

10 320

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;

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

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

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

Не Безопасно

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

безопасное

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

обновление Аркадий: Я наблюдал более правильное поведение System.currentTimeMillis() на Windows 7 в Oracle Java 8. Время было возвращено с точностью до 1 миллисекунды. Исходный код в 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, такой как Meinberg, который "настраивает" тактовую частоту до нуля, а не просто периодически сбрасывает часы.

Я говорю Из личного опыта. В погодном приложении, которое я разработал, я получал случайные всплески скорости ветра. Потребовалось время для меня, чтобы поймите, что моя временная база была нарушена поведением времени часов на типичном ПК. Все мои проблемы исчезли, когда я начал использовать 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() может улучшить включают в себя:

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

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

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

о методе nanoTime:

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

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

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