Meet de verstreken tijd in Java

1. Overzicht

In dit artikel gaan we kijken hoe we de verstreken tijd in Java kunnen meten. Hoewel dit misschien eenvoudig klinkt, zijn er een paar valkuilen waar we ons bewust van moeten zijn.

We onderzoeken standaard Java-klassen en externe pakketten die functionaliteit bieden om de verstreken tijd te meten.

2. Eenvoudige metingen

2.1. currentTimeMillis ()

Wanneer we een vereiste tegenkomen om de verstreken tijd in Java te meten, kunnen we dit proberen als:

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

Als we naar de code kijken, is het volkomen logisch. We krijgen aan het begin een tijdstempel en we krijgen een ander tijdstempel wanneer de code klaar is. De verstreken tijd is het verschil tussen deze twee waarden.

Echter, het resultaat kan en zal onnauwkeurig zijn als System.currentTimeMillis () maatregelen wandklok tijd. De wandkloktijd kan om vele redenen veranderen, bijv. het wijzigen van de systeemtijd kan de resultaten beïnvloeden of een schrikkelseconde zal het resultaat verstoren.

2.2. nanoTime ()

Een andere methode in java.lang.System klasse is nanoTime (). Als we de Java-documentatie bekijken, vinden we de volgende verklaring:

"Deze methode kan alleen worden gebruikt om de verstreken tijd te meten en is niet gerelateerd aan enig ander begrip van systeem- of wandkloktijd."

Laten we het gebruiken:

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

De code is in principe hetzelfde als voorheen. Het enige verschil is de methode die wordt gebruikt om tijdstempels op te halen - nanoTime () in plaats van currentTimeMillis ().

Laten we dat ook opmerken nanoTime ()geeft uiteraard de tijd terug in nanoseconden. Daarom, als de verstreken tijd wordt gemeten in een andere tijdseenheid, moeten we deze dienovereenkomstig omrekenen.

Om bijvoorbeeld naar milliseconden om te rekenen, moeten we het resultaat in nanoseconden delen door 1.000.000.

Een andere valkuil met nanoTime () is dat hoewel het een nauwkeurigheid van nanoseconde biedt, garandeert het geen nanoseconde resolutie (d.w.z. hoe vaak de waarde wordt bijgewerkt).

Het garandeert echter wel dat de resolutie minstens zo goed zal zijn als die van currentTimeMillis ().

3. Java 8

Als we Java 8 gebruiken, kunnen we het nieuwe proberen java.time.Instant en java.time.Duration klassen. Beide zijn onveranderlijk, thread-safe en gebruiken hun eigen tijdschaal, de Java-tijdschaal, net als alle klassen binnen het nieuwe java.time API.

3.1. Java-tijdschaal

De traditionele manier om tijd te meten is om een ​​dag op te splitsen in 24 uur van 60 minuten van 60 seconden, wat neerkomt op 86.400 seconden per dag. Zonnedagen zijn echter niet altijd even lang.

De UTC-tijdschaal staat eigenlijk toe dat een dag 86.399 of 86.401 SI-seconden heeft. Een SI-seconde is een wetenschappelijke "Standaard Internationale seconde" en wordt gedefinieerd door perioden van straling van het cesium 133-atoom). Dit is nodig om de dag op één lijn te houden met de zon.

De Java-tijdschaal verdeelt elke kalenderdag in precies 86.400 onderverdelingen, ook wel seconden genoemd. Er zijn geen schrikkelseconden.

3.2. Onmiddellijk Klasse

De Onmiddellijk class vertegenwoordigt een moment op de tijdlijn. In feite is het een numerieke tijdstempel sinds het standaard Java-tijdperk van 1970-01-01T00: 00: 00Z.

Om de huidige tijdstempel te krijgen, kunnen we de Instant.now () statische methode. Met deze methode kunt u een optioneel Klok parameter. Indien weggelaten, wordt de systeemklok in de standaardtijdzone gebruikt.

We kunnen start- en eindtijden opslaan in twee variabelen, zoals in eerdere voorbeelden. Vervolgens kunnen we de verstreken tijd tussen beide momenten berekenen.

We kunnen bovendien de Looptijd klasse en het is tussen() methode om de duur tussen twee te verkrijgen Onmiddellijk voorwerpen. Ten slotte moeten we converteren Looptijd tot milliseconden:

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

4. Stopwatch

Als we verder gaan met bibliotheken, biedt Apache Commons Lang de Stopwatch klasse die kan worden gebruikt om de verstreken tijd te meten.

4.1. Afhankelijkheid van Maven

We kunnen de nieuwste versie krijgen door de pom.xml bij te werken:

 org.apache.commons commons-lang3 3.7 

De laatste versie van de afhankelijkheid kan hier worden gecontroleerd.

4.2. Verstreken tijd meten met Stopwatch

Allereerst moeten we een instantie van de klas krijgen en dan kunnen we eenvoudig de verstreken tijd meten:

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

Zodra we een horloge hebben lopen, kunnen we de code uitvoeren die we willen benchmarken en aan het einde noemen we gewoon de hou op() methode. Ten slotte bellen we om het daadwerkelijke resultaat te krijgen krijg tijd():

watch.stop (); System.out.println ("Verstreken tijd:" + watch.getTime ()); // Afdrukken: verstreken tijd: 2501

Stopwatch heeft een paar aanvullende hulpmethoden die we kunnen gebruiken om onze meting te pauzeren of te hervatten. Dit kan handig zijn als we onze benchmark complexer moeten maken.

Laten we tot slot opmerken dat de klasse niet thread-safe is.

5. Conclusie

Er zijn veel manieren om tijd in Java te meten. We hebben een zeer "traditionele" (en onnauwkeurige) manier behandeld door te gebruiken currentTimeMillis (). Bovendien hebben we Apache Common's Stopwatch en keek naar de nieuwe klassen die beschikbaar zijn in Java 8.

In het algemeen, voor eenvoudige en correcte metingen van de verstreken tijd, de nanoTime () methode is voldoende. Het is ook korter om te typen dan currentTimeMillis ().

Laten we echter opmerken dat we voor een goede benchmarking, in plaats van de tijd handmatig te meten, een raamwerk zoals de Java Microbenchmark Harness (JMH) kunnen gebruiken. Dit onderwerp valt buiten het bestek van dit artikel, maar we hebben het hier onderzocht.

Eindelijk, zoals altijd, is de code die tijdens de discussie is gebruikt, te vinden op GitHub.