System.currentTimeMillis () vs. new Date () vs. Calendar.getInstance (). GetTime ()

238

Welche Auswirkungen hat die Verwendung in Java auf Leistung und Ressourcen?

System.currentTimeMillis() 

vs.

new Date() 

vs.

Calendar.getInstance().getTime()

Soweit ich weiß, System.currentTimeMillis()ist es am effizientesten. In den meisten Anwendungen müsste dieser lange Wert jedoch in ein Datum oder ein ähnliches Objekt konvertiert werden, um etwas zu tun, das für den Menschen von Bedeutung ist.

Vihung
quelle

Antworten:

241

System.currentTimeMillis()ist offensichtlich das effizienteste, da es nicht einmal ein Objekt erstellt, sondern new Date()wirklich nur eine dünne Hülle über einen langen Zeitraum ist, sodass es nicht weit dahinter liegt. CalendarAndererseits ist es relativ langsam und sehr komplex, da es sich mit der beträchtlichen Komplexität und allen Kuriositäten befassen muss, die Datums- und Uhrzeitangaben (Schaltjahre, Sommerzeit, Zeitzonen usw.) inhärent sind.

Im Allgemeinen ist es eine gute Idee, sich nur mit langen Zeitstempeln oder DateObjekten in Ihrer Anwendung zu befassen und diese nur dann zu verwenden, Calendarwenn Sie tatsächlich Datums- / Zeitberechnungen durchführen oder Datumsangaben formatieren müssen, um sie dem Benutzer anzuzeigen. Wenn Sie viel davon tun müssen, ist die Verwendung von Joda Time wahrscheinlich eine gute Idee, um eine sauberere Benutzeroberfläche und eine bessere Leistung zu erzielen.

Michael Borgwardt
quelle
2
Was ist der Unterschied zwischen Zeitstempel und currentMillis?
Pinkpanther
1
@pinkpanther: "Zeitstempel" wird normalerweise verwendet, um eine Ganzzahl / Länge zu beschreiben, die einen Zeitpunkt beschreibt, wenn sie als Sekunden oder Millisekunden seit einem "Epochenstart" interpretiert wird. Mit anderen Worten, currentTimeMillis () gibt einen Zeitstempel zurück.
Michael Borgwardt
42

Mit Blick auf das JDK hat der innerste Konstruktor für Calendar.getInstance():

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

es macht also schon automatisch das, was du vorschlägst. Der Standardkonstruktor von Date enthält Folgendes:

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

Es ist also wirklich nicht erforderlich, die Systemzeit speziell abzurufen, es sei denn, Sie möchten etwas damit rechnen, bevor Sie Ihr Kalender- / Datumsobjekt damit erstellen. Außerdem muss ich joda-time als Ersatz für Javas eigene Kalender- / Datumsklassen empfehlen, wenn Sie viel mit Datumsberechnungen arbeiten möchten .

Esko
quelle
22

Wenn Sie ein Datum verwenden, empfehle ich dringend, dass Sie jodatime verwenden, http://joda-time.sourceforge.net/ . Unter Verwendung System.currentTimeMillis()für Felder , die sind Daten klingen wie eine sehr schlechte Idee , weil Sie mit einer Menge von nutzlosem Code am Ende werden.

Sowohl das Datum als auch der Kalender sind stark belastet, und der Kalender ist definitiv der schlechteste von allen.

Ich würde Ihnen raten, diese zu verwenden, System.currentTimeMillis()wenn Sie tatsächlich mit Millisekunden arbeiten, zum Beispiel so

 long start = System.currentTimeMillis();
    .... do something ...
 long elapsed = System.currentTimeMillis() -start;
Krosenvold
quelle
28
Ich wollte dies kommentieren, da Ihr Beispiel genau eines der Dinge ist, für die Sie System.currentTimeMillis () NICHT verwenden sollten . Da es sich nicht um eine monotone Taktquelle handelt, können Sie die verstrichene Zeit damit nicht zuverlässig berechnen. Wenn die Systemuhr geändert wird, während der von Ihnen zeitgesteuerte Code ausgeführt wird, erhalten Sie seltsame (z. B. negative) Ergebnisse. Anstelle Verwendung System.nanoTime (), das ist monotone , wenn die zugrundeliegenden System Träger, eine Taktquelle (siehe bugs.java.com/bugdatabase/view_bug.do?bug_id=6458294 )
rem
System.currentTimeMillis selbst ist von der Zeitzone nicht betroffen. Das Ändern der Systemzeit wirkt sich auf System.nanotime genauso aus wie auf System.currentTimeMillis
Viktor
12

Ich bevorzuge es, den von zurückgegebenen Wert System.currentTimeMillis()für alle Arten von Berechnungen zu verwenden und nur zu verwenden Calendaroder Datewenn ich wirklich einen Wert anzeigen muss, der von Menschen gelesen wird. Dies verhindert auch 99% Ihrer Fehler bei der Sommerzeit. :) :)

Bombe
quelle
12

Auf meinem Computer habe ich versucht, es zu überprüfen. Mein Ergebnis:

Calendar.getInstance (). GetTime () (* 1000000 mal) = 402 ms
neues Datum (). getTime (); (* 1000000 mal) = 18 ms
System.currentTimeMillis () (* 1000000 mal) = 16 ms

Vergessen Sie nicht GC (wenn Sie Calendar.getInstance()oder verwenden new Date())

Puzirki
quelle
1
Ich
7

Abhängig von Ihrer Anwendung sollten Sie System.nanoTime()stattdessen die Verwendung in Betracht ziehen .

MykennaC
quelle
Warum, seine Frage war über Ressourcen und Leistung, nanoTime () verwendet mehr Ressourcen
WolfmanDragon
Ich habe es erwähnt, weil es eine Option ist, die sonst niemand vorgeschlagen hat. Auf dem Poster wurde keine Plattform angegeben. Der SDN-Fehler 6876279 legt nahe, dass currentTimeMillis () und nanoTime () in einigen JDK-Versionen ungefähr gleich sind. Das Poster gab auch nicht ihre Genauigkeitsanforderungen an, für die die ursprüngliche Liste möglicherweise unzureichend ist.
MykennaC
4
So spät dies auch sein mag, alle Beispiele in der Frage haben eine absolute Vorstellung davon, wie spät es ist, z. 1.348.770.313.071 Millis seit Beginn der Unix-Epoche. Die zurückgegebene Zeit nanoTimeist relativ (normalerweise zum Start des Programms) und wäre Unsinn, wenn Sie versuchen würden, daraus ein Datum zu machen.
Dünen
Ja, aber Sie könnten currentTimeilli und nano beim Programmstart in statischem Code speichern und diese dann als Offsets verwenden, um einen genauen Nano von milli mit einem doppelten var = currentTimeStart - nanoTimeStart + nanoTimeNow
tgkprog
3

Ich habe es versucht:

        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);

Und das Ergebnis war:

Datum (): 199

currentTimeMillis (): 3

Wiji
quelle
4
Dies ist ein Mikro-Benchmark, und Sie sollten darauf achten, den erzielten Ergebnissen zu vertrauen. Schauen Sie sich stackoverflow.com/questions/504103/… an .
Axel
1
Dieser Benchmark ist nicht signifikant oder zeigt besser, dass das Betriebssystem unter Java eine Rolle spielt. Ich habe den gleichen Benchmark ein Dutzend Mal in einer Schleife ausgeführt (Verschieben der Initialisierung von "Jetzt" und "Ergebnis" aus der Schleife), und ich hatte bei jedem Lauf nette Unterschiede: Datum (): 322 bis 330; currentTimeMillis (): 319 bis 322. Bei einigen anderen Läufen hatte ich Date (): 312 bis 318; currentTimeMillis (): 324 bis 335. IMHO sind sie also in realen Fällen ziemlich gleichwertig (auch unter Berücksichtigung der Datumsquelle). JFYI, ich habe Java7 unter Ubuntu verwendet.
Sampisa
0

System.currentTimeMillis() ist offensichtlich die schnellste, da es sich nur um einen Methodenaufruf handelt und kein Garbage Collector erforderlich ist.

Ramón
quelle
14
Ihre Antwort hat keinen Wert, da sie nur eine Teilmenge der zuvor genehmigten Antwort ist. Sie sollten versuchen, nicht auf diese Weise zu antworten, insbesondere wenn Sie nicht bedenken, dass es sich um eine sehr alte Frage mit einer bereits vorhandenen Qualitätsantwort handelt.
Nicklas Gnejs Eriksson
1
Zweitens ist für kurzfristige Objekte im Eden-Raum ohnehin kein Garbage Collector erforderlich.
Niels Bech Nielsen