Verstrichene Zeit in Java messen

1. Übersicht

In diesem Artikel sehen wir uns an, wie die verstrichene Zeit in Java gemessen wird. Dies mag einfach klingen, aber es gibt einige Fallstricke, die wir beachten müssen.

Wir werden Standard-Java-Klassen und externe Pakete untersuchen, die Funktionen zum Messen der verstrichenen Zeit bieten.

2. Einfache Messungen

2.1. currentTimeMillis ()

Wenn wir die Anforderung haben, die verstrichene Zeit in Java zu messen, versuchen wir dies möglicherweise wie folgt:

long start = System.currentTimeMillis(); // ... long finish = System.currentTimeMillis(); long timeElapsed = finish - start;

Wenn wir uns den Code ansehen, ist das absolut sinnvoll. Wir erhalten zu Beginn einen Zeitstempel und nach Beendigung des Codes einen weiteren Zeitstempel. Die verstrichene Zeit ist die Differenz zwischen diesen beiden Werten.

Jedoch kann das Ergebnis und wird als ungenau sein System.currentTimeMillis () Maßnahmen wanduhr Zeit. Die Wanduhrzeit kann sich aus vielen Gründen ändern, z. B. kann eine Änderung der Systemzeit die Ergebnisse beeinflussen oder eine Schaltsekunde kann das Ergebnis stören.

2.2. nanoTime ()

Eine andere Methode in der Klasse java.lang.System ist nanoTime () . Wenn wir uns die Java-Dokumentation ansehen, finden wir die folgende Aussage:

"Diese Methode kann nur zur Messung der verstrichenen Zeit verwendet werden und steht in keinem Zusammenhang mit einem anderen Begriff der System- oder Wanduhrzeit."

Lass es uns benutzen:

long start = System.nanoTime(); // ... long finish = System.nanoTime(); long timeElapsed = finish - start;

Der Code ist im Grunde der gleiche wie zuvor. Der einzige Unterschied besteht in der Methode zum Abrufen von Zeitstempeln - nanoTime () anstelle von currentTimeMillis () .

Beachten Sie auch, dass nanoTime () offensichtlich die Zeit in Nanosekunden zurückgibt. Wenn die verstrichene Zeit in einer anderen Zeiteinheit gemessen wird, müssen wir sie daher entsprechend umrechnen.

Um beispielsweise in Millisekunden umzuwandeln, müssen wir das Ergebnis in Nanosekunden durch 1.000.000 teilen.

Eine weitere Gefahr bei nanoTime () besteht darin, dass es zwar eine Nanosekundengenauigkeit bietet, jedoch keine Nanosekundenauflösung garantiert (dh wie oft der Wert aktualisiert wird).

Es wird jedoch garantiert, dass die Auflösung mindestens so gut ist wie die von currentTimeMillis () .

3. Java 8

Wenn wir Java 8 verwenden, können wir die neuen Klassen java.time.Instant und java.time.Duration ausprobieren . Beide sind unveränderlich, threadsicher und verwenden ihre eigene Zeitskala, die Java-Zeitskala, wie alle Klassen in der neuen java.time- API.

3.1. Java-Zeitskala

Die traditionelle Methode zur Zeitmessung besteht darin, einen Tag in 24 Stunden von 60 Minuten und 60 Sekunden zu unterteilen, was 86.400 Sekunden pro Tag ergibt. Sonnentage sind jedoch nicht immer gleich lang.

Die UTC-Zeitskala erlaubt einem Tag tatsächlich 86,399 oder 86,401 SI-Sekunden. Eine SI-Sekunde ist eine wissenschaftliche „Standard International-Sekunde“ und wird durch Strahlungsperioden des Cäsium-133-Atoms definiert. Dies ist erforderlich, um den Tag auf die Sonne auszurichten.

Die Java-Zeitskala unterteilt jeden Kalendertag in genau 86.400 Unterteilungen, die als Sekunden bezeichnet werden . Es gibt keine Schaltsekunden.

3.2. Sofortige Klasse

Die Instant- Klasse repräsentiert einen Instant auf der Timeline. Grundsätzlich handelt es sich um einen numerischen Zeitstempel seit der Standard-Java-Epoche 1970-01-01T00: 00: 00Z .

Um den aktuellen Zeitstempel abzurufen , können wir die statische Methode Instant.now () verwenden. Diese Methode ermöglicht die Übergabe eines optionalen Clock- Parameters. Wenn nicht angegeben, wird die Systemuhr in der Standardzeitzone verwendet.

Wir können Start- und Endzeiten wie in den vorherigen Beispielen in zwei Variablen speichern. Als nächstes können wir die zwischen beiden Zeitpunkten verstrichene Zeit berechnen.

Wir können zusätzlich die Duration- Klasse und die Between () -Methode verwenden, um die Dauer zwischen zwei Instant- Objekten zu ermitteln. Schließlich müssen wir die Dauer in Millisekunden umrechnen :

Instant start = Instant.now(); // CODE HERE Instant finish = Instant.now(); long timeElapsed = Duration.between(start, finish).toMillis();

4. StopWatch

Apache Commons Lang stellt die StopWatch- Klasse zur Verfügung, mit der die verstrichene Zeit gemessen werden kann.

4.1. Maven-Abhängigkeit

Wir können die neueste Version erhalten, indem wir die Datei pom.xml aktualisieren:

 org.apache.commons commons-lang3 3.7 

Die neueste Version der Abhängigkeit kann hier überprüft werden.

4.2. Verstrichene Zeit mit StopWatch messen

Zuerst müssen wir eine Instanz der Klasse erhalten und dann können wir einfach die verstrichene Zeit messen:

StopWatch watch = new StopWatch(); watch.start();

Sobald eine Uhr läuft, können wir den Code ausführen, den wir vergleichen möchten, und am Ende rufen wir einfach die stop () -Methode auf. Um das tatsächliche Ergebnis zu erhalten, rufen wir schließlich getTime () auf :

watch.stop(); System.out.println("Time Elapsed: " + watch.getTime()); // Prints: Time Elapsed: 2501

StopWatch verfügt über einige zusätzliche Hilfsmethoden, mit denen wir unsere Messung anhalten oder fortsetzen können. Dies kann hilfreich sein, wenn wir unseren Benchmark komplexer gestalten müssen.

Beachten Sie abschließend, dass die Klasse nicht threadsicher ist.

5. Schlussfolgerung

Es gibt viele Möglichkeiten, die Zeit in Java zu messen. Wir haben mit currentTimeMillis () einen sehr „traditionellen“ (und ungenauen) Weg beschrieben . Zusätzlich haben wir StopWatch von Apache Common überprüft und uns die neuen Klassen angesehen, die in Java 8 verfügbar sind.

Insgesamt reicht für einfache und korrekte Messungen der verstrichenen Zeit die Methode nanoTime () aus. Die Eingabe ist auch kürzer als currentTimeMillis () .

Beachten Sie jedoch, dass wir für ein korrektes Benchmarking anstelle einer manuellen Zeitmessung ein Framework wie das Java Microbenchmark Harness (JMH) verwenden können. Dieses Thema geht über den Rahmen dieses Artikels hinaus, aber wir haben es hier untersucht.

Schließlich ist der während der Diskussion verwendete Code wie immer auf GitHub zu finden.