Mål forløbet tid i Java

1. Oversigt

I denne artikel skal vi se på, hvordan man måler forløbet tid i Java. Selvom dette måske lyder let, er der et par faldgruber, som vi skal være opmærksomme på.

Vi undersøger standard Java-klasser og eksterne pakker, der giver funktionalitet til at måle forløbet tid.

2. Enkle målinger

2.1. currentTimeMillis ()

Når vi støder på et krav om at måle forløbet tid i Java, kan vi prøve at gøre det som:

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

Hvis vi ser på koden, giver det mening. Vi får et tidsstempel i starten, og vi får et andet tidsstempel, når koden er færdig. Forløbet tid er forskellen mellem disse to værdier.

Imidlertid, resultatet kan og vil være unøjagtigt som System.currentTimeMillis () foranstaltninger vægur tid. Vægurets tid kan ændre sig af mange grunde, f.eks. ændring af systemtid kan påvirke resultaterne, eller et spring sekund vil forstyrre resultatet.

2.2. nanoTime ()

En anden metode i java.lang.System klasse er nanoTime (). Hvis vi ser på Java-dokumentationen, finder vi følgende udsagn:

"Denne metode kan kun bruges til at måle forløbet tid og er ikke relateret til nogen anden forestilling om system eller vægurstid."

Lad os bruge det:

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

Koden er dybest set den samme som før. Den eneste forskel er metoden, der bruges til at få tidsstempler - nanoTime () i stedet for currentTimeMillis ().

Lad os også bemærke det nanoTime ()returnerer naturligvis tid i nanosekunder. Derfor, hvis den forløbne tid måles i en anden tidsenhed, skal vi konvertere den i overensstemmelse hermed.

For eksempel, for at konvertere til millisekunder skal vi dele resultatet i nanosekunder med 1.000.000.

En anden faldgrube med nanoTime () er det selvom det giver nanosekundpræcision, garanterer det ikke nanosekundopløsning (dvs. hvor ofte værdien opdateres).

Det garanterer dog, at opløsningen bliver mindst lige så god som den currentTimeMillis ().

3. Java 8

Hvis vi bruger Java 8 - kan vi prøve det nye java.tid. øjeblikkelig og java.time.Duration klasser. Begge er uforanderlige, trådsikre og bruger deres egen tidsskala, the Java tidsskala, ligesom alle klasser inden for det nye java.tid API.

3.1. Java tidsskala

Den traditionelle måde at måle tid på er at opdele en dag i 24 timer på 60 minutter på 60 sekunder, hvilket giver 86.400 sekunder om dagen. Soldage er dog ikke altid lige lange.

UTC-tidsskala tillader faktisk, at en dag har 86.399 eller 86.401 SI sekunder. Et SI-sekund er et videnskabeligt ”Standard International second” og defineres af perioder med stråling af cæsium 133-atomet). Dette er nødvendigt for at holde dagen på linje med solen.

Java Time-Scale opdeler hver kalenderdag i nøjagtigt 86.400 underinddelinger, kendt som sekunder. Der er ingen spring sekunder.

3.2. Øjeblikkelig Klasse

Det Øjeblikkelig klasse repræsenterer et øjeblik på tidslinjen. Dybest set er det en numerisk tidsstempel siden standard Java-epoken af 1970-01-01T00: 00: 00Z.

For at få det aktuelle tidsstempel kan vi bruge Øjeblikkelig. Nu () statisk metode. Denne metode tillader overførsel af en valgfri Ur parameter. Hvis den udelades, bruger den systemuret i standardtidszonen.

Vi kan gemme start- og sluttider i to variabler, som i tidligere eksempler. Dernæst kan vi beregne forløbet tid mellem begge øjeblikke.

Vi kan desuden bruge Varighed klasse og det er mellem() metode til at opnå varigheden mellem to Øjeblikkelig genstande. Endelig er vi nødt til at konvertere Varighed til millisekunder:

Øjeblikkelig start = Øjeblikkelig. Nu (); // KODE HER Øjeblikkelig finish = Instant.now (); long timeElapsed = Duration.between (start, finish) .toMillis ();

4. Stopur

Apache Commons Lang går videre til biblioteker Stopur klasse, der kan bruges til at måle forløbet tid.

4.1. Maven afhængighed

Vi kan få den nyeste version ved at opdatere pom.xml:

 org.apache.commons commons-lang3 3.7 

Den seneste version af afhængigheden kan kontrolleres her.

4.2. Måling af forløbet tid med Stopur

Først og fremmest er vi nødt til at få en forekomst af klassen, og så kan vi simpelthen måle den forløbne tid:

StopWatch ur = nyt StopWatch (); watch.start ();

Når vi har et ur, der kører, kan vi udføre den kode, vi vil benchmark, og i slutningen kalder vi simpelthen hold op() metode. Endelig kalder vi for at få det faktiske resultat getTime ():

watch.stop (); System.out.println ("Forløbet tid:" + watch.getTime ()); // Udskrifter: Forløbet tid: 2501

Stopur har et par ekstra hjælpemetoder, som vi kan bruge til at stoppe eller genoptage vores måling. Dette kan være nyttigt, hvis vi har brug for at gøre vores benchmark mere kompleks.

Lad os endelig bemærke, at klassen ikke er trådsikker.

5. Konklusion

Der er mange måder at måle tid på Java. Vi har dækket en meget “traditionel” (og unøjagtig) måde ved hjælp af currentTimeMillis (). Derudover kontrollerede vi Apache Common's Stopur og kiggede på de nye klasser, der er tilgængelige i Java 8.

Samlet set er det for enkle og korrekte målinger af den forløbne tid nanoTime () metoden er tilstrækkelig. Det er også kortere at skrive end currentTimeMillis ().

Lad os dog bemærke, at vi til korrekt benchmarking i stedet for at måle tid manuelt kan bruge en ramme som Java Microbenchmark Harness (JMH). Dette emne går ud over omfanget af denne artikel, men vi udforskede det her.

Endelig, som altid, kan koden, der blev brugt under diskussionen, findes på GitHub.