Messen Sie die abgelaufene Zeit in Java

Verstrichene Zeit in Java messen

1. Überblick

In diesem Artikel erfahren Sie, wie Sie die verstrichene Zeit in Java messen. While this may sound easy, there’re a few pitfalls that we must be aware of.

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 eine Anforderung zum Messen der verstrichenen Zeit in Java haben, versuchen wir es 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 bekommen zu Beginn einen Zeitstempel und einen weiteren Zeitstempel, wenn der Code fertig ist. Die verstrichene Zeit ist die Differenz zwischen diesen beiden Werten.

Die Wanduhrzeit vonthe result may and will be inaccurate as System.currentTimeMillis() measures wall-clock time. kann sich jedoch aus vielen Gründen ändern, z. Das Ändern der Systemzeit kann sich auf die Ergebnisse auswirken, oder eine Schaltsekunde stört das Ergebnis.

2.2. nanoTime()

Eine andere Methode in der Klassejava.lang.SystemistnanoTime(). Wenn wir uns dieJava documentation 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.“

Verwenden wir es:

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 voncurrentTimeMillis().

Beachten Sie auch, dassnanoTime() offensichtlich die Zeit in Nanosekunden zurückgibt. Wenn also die abgelaufene Zeit in einer anderen Zeiteinheit gemessen wird, müssen wir sie entsprechend umrechnen.

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

Eine weitere Gefahr mitnanoTime() ist, dasseven though it provides nanosecond precision, it doesn’t guarantee nanosecond resolution (d.h. wie oft der Wert aktualisiert wird).

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

3. Java 8

Wenn wir Java 8 verwenden, können wir die neuen Klassenjava.time.Instant undjava.time.Durationausprobieren. Beide sind unveränderlich, threadsicher und verwenden ihre eigene Zeitskala, dieJava Time-Scale,, wie alle Klassen innerhalb der neuenjava.time-API.

3.1. Java-Zeitskala

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

Die UTC-Zeitskala ermöglicht tatsächlich, dass ein Tag 86.399 oder 86.401 SI-Sekunden hat. Eine SI-Sekunde ist eine wissenschaftliche "internationale Standardsekunde" und wird durch Bestrahlungsperioden des Cäsium-133-Atoms definiert. Dies ist erforderlich, um den Tag auf die Sonne auszurichten.

The Java Time-Scale divides each calendar day into exactly 86.400 subdivisions, known as seconds. Es gibt keine Schaltsekunden.

3.2. Instant Klasse

Die KlasseInstant repräsentiert einen Moment auf der Zeitachse. Grundsätzlich handelt es sich um einen numerischen Zeitstempel seit der Standard-Java-Epoche von1970-01-01T00:00:00Z.

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

We can store start and finish times in two variables, as in previous examples. Als nächstes können wir die zwischen beiden Zeitpunkten verstrichene Zeit berechnen.

Wir können zusätzlich die KlasseDurationund die Methodebetween()verwenden, um die Dauer zwischen zweiInstant-Objekten zu ermitteln. Schließlich müssen wirDuration in Millisekunden umrechnen:

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

4. StopWatch

Bei den Bibliotheken stellt Apache Commons Lang die KlasseStopWatchbereit, 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 inhere überprüft werden.

4.2. Verstrichene Zeit mitStopWatch 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 Methodestop()auf. Um das tatsächliche Ergebnis zu erhalten, rufen wir schließlichgetTime() auf:

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

StopWatch has a few additional helper methods that we can use in order to pause or resume our measurement. Dies kann hilfreich sein, wenn wir unseren Benchmark komplexer gestalten müssen.

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

5. Fazit

Es gibt viele Möglichkeiten, die Zeit in Java zu messen. Wir haben einen sehr "traditionellen" (und ungenauen) Weg mitcurrentTimeMillis() behandelt. Zusätzlich haben wirStopWatchvon Apache Common überprüft und uns die neuen Klassen angesehen, die in Java 8 verfügbar sind.

Insgesamt ist für einfache und korrekte Messungen der verstrichenen Zeit dienanoTime()-Methode ausreichend. Die Eingabe ist auch kürzer alscurrentTimeMillis().

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 habenit here untersucht.

Schließlich kann wie immer der während der Diskussion verwendete Codeover on GitHub gefunden werden.