System.currentTimeMillis () против новой даты () против Calendar.getInstance (). GetTime ()

239

В Java, каковы последствия использования производительности и ресурсов

System.currentTimeMillis() 

против

new Date() 

против

Calendar.getInstance().getTime()

Насколько я понимаю, System.currentTimeMillis()это самый эффективный. Однако в большинстве приложений это длинное значение необходимо преобразовать в Date или какой-либо подобный объект, чтобы сделать что-то значимое для человека.

Vihung
источник

Ответы:

242

System.currentTimeMillis()Очевидно, он наиболее эффективен, поскольку он даже не создает объект, но new Date()на самом деле является просто тонкой оберткой для длинных, поэтому он не сильно отстает. Calendarс другой стороны, он относительно медленный и очень сложный, поскольку имеет дело со значительной сложностью и всеми странностями, присущими датам и временам (високосные годы, летнее время, часовые пояса и т. д.).

Как правило, рекомендуется иметь дело только с длинными метками времени или Dateобъектами в вашем приложении и использовать их только Calendarтогда, когда вам действительно необходимо выполнить вычисления даты / времени или отформатировать даты для их отображения пользователю. Если вам приходится много делать, возможно, Joda Time - хорошая идея для более чистого интерфейса и лучшей производительности.

Майкл Боргвардт
источник
2
В чем разница между отметкой времени и текущим миллисекундом?
Розовая пантера
1
@pinkpanther: «отметка времени» обычно используется для описания целого числа / длинного, которое описывает момент времени, когда интерпретируется как секунды или миллисекунды с момента «начала эпохи». Другими словами, currentTimeMillis () возвращает отметку времени.
Майкл Боргвардт
43

Глядя на JDK, самый внутренний конструктор для Calendar.getInstance()этого имеет:

public GregorianCalendar(TimeZone zone, Locale aLocale) {
    super(zone, aLocale);
    gdate = (BaseCalendar.Date) gcal.newCalendarDate(zone);
    setTimeInMillis(System.currentTimeMillis());
}

поэтому он автоматически делает то, что вы предлагаете. Конструктор даты по умолчанию содержит это:

public Date() {
    this(System.currentTimeMillis());
}

Таким образом, действительно нет необходимости получать системное время специально, если только вы не захотите поработать с ним перед созданием объекта Calendar / Date. Также я должен порекомендовать joda-time для замены собственных классов календаря / даты в Java, если ваша цель - много работать с вычислениями даты.

Эско
источник
22

Если вы ИСПОЛЬЗУЕТЕ свидание, тогда я настоятельно рекомендую вам использовать jodatime, http://joda-time.sourceforge.net/ . Использование System.currentTimeMillis()для полей, которые являются датами, звучит как очень плохая идея, потому что в итоге вы получите много бесполезного кода.

И дата, и календарь серьезно сорваны, и Календарь, безусловно, худший из всех.

Я бы посоветовал вам использовать, System.currentTimeMillis()когда вы на самом деле работаете с миллисекундами, например, вот так

 long start = System.currentTimeMillis();
    .... do something ...
 long elapsed = System.currentTimeMillis() -start;
krosenvold
источник
28
Я хотел прокомментировать это, потому что ваш пример - это как раз то, для чего вы НЕ должны использовать System.currentTimeMillis (); это не монотонный источник часов, поэтому вы не можете надежно рассчитать прошедшее время с ним. Если системные часы меняются во время выполнения кода, который вы синхронизируете, вы получите странные (например, отрицательные) результаты. Вместо этого используйте System.nanoTime (), которая является монотонной, если базовая система поддерживает такой источник синхронизации (см. Bugs.java.com/bugdatabase/view_bug.do?bug_id=6458294 )
rem
Сам System.currentTimeMillis не зависит от часового пояса. Изменение системного времени будет влиять на System.nanotime так же, как System.currentTimeMillis
Виктор
12

Я предпочитаю использовать значение, возвращаемое System.currentTimeMillis()для всех видов вычислений, и использовать только Calendarили Dateесли мне нужно действительно отобразить значение, которое читают люди. Это также предотвратит 99% ваших ошибок при переходе на летнее время. :)

Бомбы
источник
12

На моей машине я попытался проверить это. Мой результат:

Calendar.getInstance (). GetTime () (* 1000000 раз) = 402 мс
new Date (). getTime (); (* 1000000 раз) = 18 мс
System.currentTimeMillis () (* 1000000 раз) = 16 мс

Не забывайте о GC (если вы используете Calendar.getInstance()или new Date())

Puzirki
источник
1
Интересно, будет ли какая-то разница, если многие потоки будут вызывать одно и то же между другими процессами
tgkprog
7

В зависимости от вашего приложения, вы можете рассмотреть возможность использования System.nanoTime()вместо.

MykennaC
источник
Почему, его вопрос был о ресурсах и производительности, nanoTime () использует больше ресурсов
WolfmanDragon
Я упомянул об этом, потому что это вариант, который никто не предложил. На плакате не указана платформа. Ошибка SDN 6876279 предполагает, что currentTimeMillis () и nanoTime () примерно одинаковы в некоторых версиях JDK. В плакате также не указана их точность, для которой первоначальный список может оказаться неадекватным.
MykennaC
4
Поздно, как это может быть, все примеры в вопросе имеют абсолютное представление о том, который час, например. 1 348 770 313 071 миллис с начала эпохи Unix. Время, которое nanoTimeвозвращается, является относительным (обычно к началу программы) и будет бессмысленным, если вы попытаетесь превратить его в дату.
Дюны
да, но вы можете сохранить currentTimeilli и nano в некотором статическом коде при запуске программы, а затем использовать их в качестве смещений для получения точного nano из milli, используя двойное var = currentTimeStart - nanoTimeStart + nanoTimeNow
tgkprog
3

Я попробовал это:

        long now = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            new Date().getTime();
        }
        long result = System.currentTimeMillis() - now;

        System.out.println("Date(): " + result);

        now = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            System.currentTimeMillis();
        }
        result = System.currentTimeMillis() - now;

        System.out.println("currentTimeMillis(): " + result);

И результат был:

Дата (): 199

currentTimeMillis (): 3

wiji
источник
4
Это микро тест, и вы должны быть осторожны, чтобы доверять полученным результатам. Посмотрите на stackoverflow.com/questions/504103/… .
Аксель
1
Этот тест не имеет значения, или, что лучше, он показывает, что операционная система на Java имеет значение. Я запускал один и тот же тест в цикле десятки раз (убирая инициализацию «сейчас» и «результат» из цикла), и у меня были забавные различия при каждом запуске: Date (): от 322 до 330; currentTimeMillis (): от 319 до 322. На некоторых других запусках у меня было Date (): от 312 до 318; currentTimeMillis (): от 324 до 335. Итак, ИМХО, они вполне эквивалентны в реальных случаях (также обращаясь к источнику Date). JFYI, я использовал Java7 в Ubuntu.
Самписа
0

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

Рамона
источник
14
Ваш ответ не имеет значения, поскольку он является лишь подмножеством ранее утвержденного ответа. Вы должны стараться не отвечать таким образом, особенно если учесть, что это очень старый вопрос с уже существующим качественным ответом.
Никлас Гнейс Эрикссон
1
Во-вторых, сборщик мусора не требуется для краткосрочных объектов в пространстве Eden в любом случае.
Нильс Бек Нильсен