Comment mesurer le temps écoulé En Java? [dupliquer]
cette question a déjà une réponse ici:
- comment chronométrer L'exécution D'une méthode en Java? 36 réponses
- comment calculer le temps écoulé d'un événement en java? [duplicate] 6 réponses
je veux avoir quelque chose comme ceci:
public class Stream
{
public startTime;
public endTime;
public getDuration()
{
return startTime - endTime;
}
}
aussi, il est important que par exemple, si le startTime il est 23:00 et endTime 1:00 pour obtenir une durée de 2:00.
Quels types utiliser pour accomplir ceci en Java?
15 réponses
malheureusement, aucune des dix réponses affichées à ce jour n'est tout à fait exacte.
si vous mesurez le temps écoulé, et que vous voulez qu'il soit correct , vous devez utiliser System.nanoTime()
. Vous ne pouvez pas utiliser System.currentTimeMillis()
, à moins que votre résultat ne soit erroné.
le but de nanoTime
est de mesurer temps écoulé , et le but de currentTimeMillis
est de mesurer horloge murale du temps. Vous ne pouvez pas utiliser l'un pour l'autre but. La raison en est que l'horloge d'un ordinateur n'est pas parfaite; elle dérive toujours et doit parfois être corrigée. Cette correction peut se faire manuellement, ou dans le cas de la plupart des machines, il y a un processus qui fonctionne et publie continuellement de petites corrections à l'horloge du système ("Horloge murale"). Ceux-ci ont tendance à se produire souvent. Une autre correction de ce genre se produit chaque fois qu'il y a une seconde bissextile.
depuis nanoTime
s 'objectif est de mesurer le temps écoulé, il n'est affectée par aucune de ces petites corrections. C'est ce que vous voulez utiliser. Tout chronométrage en cours avec currentTimeMillis
sera désactivé, peut-être même négatif.
, pourriez-vous dire, "cela ne semble pas comme si cela aurait une grande importance," ce à quoi je dis, peut-être pas, mais dans l'ensemble, le code correct n'est-il pas juste mieux que le code incorrect? En outre, nanoTime
est plus court à taper de toute façon.
précédemment les disclaimers affichés sur nanoTime
n'ayant habituellement qu'une précision de microseconde sont valides. En outre, il peut prendre plus d'une microseconde entière à invoquer, selon les circonstances (comme le peut l'autre), donc ne vous attendez pas à des intervalles très très petits correctement.
Quels types utiliser pour accomplir ceci en Java?
la réponse courte est long
. Maintenant, plus sur la façon de mesurer...
système.currentTimeMillis ()
la manière" traditionnelle " de le faire est en effet d'utiliser System.currentTimeMillis()
:
long startTime = System.currentTimeMillis();
// ... do something ...
long estimatedTime = System.currentTimeMillis() - startTime;
O. A. C. L. T. Chronomètre
notez que Commons Lang a une classe StopWatch qui peut être utilisée pour mesurer le temps d'exécution en millisecondes. Il a des méthodes de méthodes comme split()
, suspend()
, resume()
, etc qui permettent de prendre des mesures à différents points de l'exécution et que vous pouvez trouver commode. Avoir un coup d'oeil.
système.nanoTime ()
vous pouvez préférer utiliser System.nanoTime()
si vous recherchez des mesures extrêmement précises du temps écoulé. De son javadoc:
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
Jamon
une autre option serait d'utiliser JAMon , un outil qui rassemble statistiques (temps d'exécution, nombre de hit, temps d'exécution moyen, min, max, etc) pour tout code qui vient entre les méthodes start() et stop (). Ci - dessous, un exemple très simple:
import com.jamonapi.*;
...
Monitor mon=MonitorFactory.start("myFirstMonitor");
...Code Being Timed...
mon.stop();
Check out cet article www.javaperformancetunning.com pour une belle présentation.
à l'Aide de l'AOP
enfin, si vous ne voulez pas encombrer votre code avec ces mesures (ou si vous ne pouvez pas changer le code existant), alors AOP serait une arme parfaite. Je ne vais pas en parler très profondément, mais je voulais au moins en parler.
ci-dessous, un aspect très simple en utilisant AspectJ et JAMon (ici, le nom court du pointcut sera utilisé pour le moniteur JAMon, d'où l'appel à thisJoinPoint.toShortString()
):
public aspect MonitorAspect {
pointcut monitor() : execution(* *.ClassToMonitor.methodToMonitor(..));
Object arround() : monitor() {
Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString());
Object returnedObject = proceed();
monitor.stop();
return returnedObject;
}
}
la définition de pointcut pourrait être facilement adaptée pour surveiller n'importe quelle méthode basée sur le nom de classe, le nom de paquet, le nom de méthode, ou n'importe quelle combinaison de ceux-ci. La mesure est vraiment un cas d'utilisation parfait pour AOP.
votre nouvelle classe:
public class TimeWatch {
long starts;
public static TimeWatch start() {
return new TimeWatch();
}
private TimeWatch() {
reset();
}
public TimeWatch reset() {
starts = System.currentTimeMillis();
return this;
}
public long time() {
long ends = System.currentTimeMillis();
return ends - starts;
}
public long time(TimeUnit unit) {
return unit.convert(time(), TimeUnit.MILLISECONDS);
}
}
Utilisation:
TimeWatch watch = TimeWatch.start();
// do something
long passedTimeInMs = watch.time();
long passedTimeInSeconds = watch.time(TimeUnit.SECONDS);
ensuite, le temps passé peut être converti à n'importe quel format que vous aimez, avec un calender par exemple
Greetz, GHad
si le but est simplement d'imprimer des informations de synchronisation grossières à vos journaux de programme, alors la solution facile pour les projets Java n'est pas d'écrire votre propre chronomètre ou des classes de minuterie, mais juste utiliser le org.apache.commons.lang.time.StopWatch
classe qui fait partie D'Apache Commons Lang.
final StopWatch stopwatch = new StopWatch();
stopwatch.start();
LOGGER.debug("Starting long calculations: {}", stopwatch);
...
LOGGER.debug("Time after key part of calcuation: {}", stopwatch);
...
LOGGER.debug("Finished calculating {}", stopwatch);
tl; dr
par exemple si le startTime il est 23:00 et endTime 1:00 pour obtenir une durée de 2:00.
impossible. Si vous avez seulement le temps de la journée, l'horloge s'arrête à minuit. Sans le contexte des dates, comment savoir si vous voulez dire 1 h le lendemain, la semaine prochaine, ou la prochaine décennie?
donc passer de 23h à 1h signifie se déplacer en arrière dans le temps 22 heures, exécutant les aiguilles de l'horloge dans le sens antihoraire. Voir le résultat ci-dessous, un négatif vingt-deux heures.
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
LocalTime.of( 23 , 0 ) , // A time-of-day without a date and without a time zone.
LocalTime.of( 1 , 0 ) // A time-of-day clock stops at midnight. So getting to 1 AM from 11 PM means going backwards 22 hours.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT-22H
la Traversée de minuit exige le contexte plus large de la date en plus de l'heure de la journée (voir ci-dessous).
Comment mesurer le temps écoulé En Java?
- capturer le moment actuel en UTC, avec
Instant.now()
. - capturez un autre de ces moments plus tard.
- Passer à la fois pour
Duration.between
. - (a) à partir de l'objet
Duration
qui en résulte, extraire un nombre de jours, d'heures, de minutes, de secondes et de fractions de seconde de 24 heures en nanosecondes en appelant les diverses méthodesto…Part
.
(b) Ou, à l'appeltoString
générer unString
dans format standard ISO 8601 dePnYnMnDTnHnMnS
.
exemple de code, utilisant une paire d'objets Instant
.
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
then , // Some other `Instant` object, captured earlier with `Instant.now()`.
Instant.now() // Capture the current moment in UTC with a resolution as fine as nanoseconds, depending on the limits of your host computer hardware clock and operating system. Generally you will get current moment in microseconds (six decimal digits of fractional second) in Java 9, 10, and 11, but only milliseconds in Java 8.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT3M27.602197S
Nouvelle Technologie En Java 8+
nous avons une nouvelle technologie pour cela maintenant intégré dans Java 8 et plus tard, le java.temps cadre de.
de java.temps
La java.le cadre temporel est défini par JSR 310 , inspiré par le projet très réussi Joda-Time , prolongé par le projet ThreeTen-Extra , et décrit dans le Oracle Tutorial .
les anciennes classes de date-heure telles que java.util.Date./Calendrier livré avec le les premières versions de Java se sont révélées mal conçues, déroutantes et gênantes. Ils sont supplantés par le java.les classes de temps.
résolution
autres réponses discuter de la résolution.
La java.les classes de temps ont nanoseconde résolution, jusqu'à neuf chiffres d'une fraction décimale d'une seconde. Par exemple, 2016-03-12T04:29:39.123456789Z
.
à la fois le vieux java.util.Date./Calendrier les classes et les classes de temps Joda ont une résolution milliseconde (3 chiffres de fraction). Par exemple, 2016-03-12T04:29:39.123Z
.
Dans Java 8, le moment actuel est extrait avec que de milliseconde en raison d'un problème hérité. En Java 9 et plus tard, l'heure actuelle peut être déterminée jusqu'à une résolution de nanoseconde à condition que l'horloge matérielle de votre ordinateur fonctionne si finement.
Heure De La Journée
Si vous voulez vraiment travailler uniquement avec l'Heure de la journée n'ayant pas de date ou de fuseau horaire, utilisez la classe LocalTime
.
LocalTime sooner = LocalTime.of ( 17, 00 );
LocalTime later = LocalTime.of ( 19, 00 );
a Duration
représente une période de temps il s'agit d'un nombre de secondes plus nanosecondes.
Duration duration = Duration.between ( sooner, later );
Dump à console.
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
tôt: 17: 00 / plus tard: 19 | 00 / Durée: PT2H
ISO 8601
notez que la sortie par défaut de Duration::toString
est dans le format standard ISO 8601 . Dans ce format, le P
marque le début (comme dans "Période"), et le T
sépare n'importe quelle partie des années-mois-jours de la partie des heures-minutes-secondes.
La Traversée De Minuit
malheureusement, travailler à l'Heure de la journée ne devient difficile que lorsque vous roulez autour de la traversée de minuit. Le LocalTime
classe gère cela en supposant que vous voulez revenir en arrière à un point antérieur dans la journée.
utilisant le même code que ci-dessus mais allant de 23:00
à 01:00
se traduit par un négatif vingt-deux heures ( PT-22H
).
LocalTime sooner = LocalTime.of ( 23, 0 );
LocalTime later = LocalTime.of ( 1, 0 );
tôt: 23: 00 / plus tard: 01:00 / Durée: PT-22H
Date-Heure
si vous avez l'intention de traverser minuit, il il est probablement logique que vous travailliez avec des valeurs de date-heure plutôt qu'avec des valeurs de l'heure-du-jour seulement.
Fuseau Horaire
Le fuseau horaireest crucial pour les dates. Nous spécifions donc trois éléments: (1) la date désirée, (2) l'heure désirée de la journée, et (3) le fuseau horaire comme contexte pour interpréter cette date et cette heure. Ici, nous choisissons arbitrairement le fuseau horaire de la zone Montréal .
si vous définissez la date en seulement un offset-de-UTC , l'utilisation d'un ZoneOffset
avec un OffsetDateTime
. Si vous avez un fuseau horaire complet (décalage plus règles pour traiter les anomalies telles que L'heure avancée), utilisez un ZoneId
avec un ZonedDateTime
.
LocalDate localDate = LocalDate.of ( 2016, 1, 23 );
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime sooner = ZonedDateTime.of ( localDate, LocalTime.of ( 23, 0 ), zoneId );
nous spécifions l'heure la plus tardive comme le jour suivant à 1:00 AM.
ZonedDateTime later = ZonedDateTime.of ( localDate.plusDays ( 1 ), LocalTime.of ( 1, 0 ), zoneId );
nous calculons le Duration
de la même manière que ci-dessus. Nous avons maintenant les deux heures attendues par cette Question.
Duration duration = Duration.between ( sooner, later );
Dump à console.
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
earlier: 2016-01-23T23:00-05: 00 [America / Montreal] / later: 2016-01-24T01:00-05: 00[America/Montreal] / durée: PT2H
Heure D'Été
si la date-heures à portée de main avait il s'agit de L'heure D'été (HNR) ou d'une autre anomalie du genre, la java.les classes de temps s'ajusteraient au besoin. Lire en classe de doc pour plus de détails.
à Propos de de java.heure
Le de java.time framework est construit dans Java 8 et plus tard. Ces classes remplacent les anciennes héritées classes de date-heure telles que java.util.Date
, Calendar
, & SimpleDateFormat
.
le Joda-Time projet, maintenant en mode maintenance , conseille la migration vers le java.temps classes.
pour en savoir plus, voir le Oracle Tutorial . Et de la recherche Débordement de pile pour de nombreux exemples et explications. La spécification est JSR 310 .
vous pouvez échanger java.temps objets directement avec votre base de données. Utiliser un JDBC driver conforme à JDBC 4.2 ou plus tard. Pas besoin de Chaînes, pas besoin de classes java.sql.*
.
où obtenir le java.les classes de temps?
- Java SE 8 , Java SE 9 , Java SE 10 , et plus tard
- Built-in.
- fait partie de L'API Java standard avec une implémentation groupée.
- Java 9 ajoute des fonctionnalités mineures et des corrections.
- Java SE 6 et Java SE 7
- une grande partie de la java.la fonctionnalité time est rétroportée à Java 6 & 7 dans ThreeTen-Backport .
- Android
- versions ultérieures des implémentations du pack Android de java.les classes de temps.
- Pour plus tôt Android (<26 ans), le ThreeTenABP "1519680920 projet" s'adapte ThreeTen-Backport (mentionné ci-dessus). Voir comment utiliser ThreeTenABP... .
le ThreeTen-Extra le projet s'étend java.temps avec des cours supplémentaires. Ce projet est un terrain d'expérimentation pour d'éventuelles futures additions à java.temps. Vous pouvez trouver ici quelques cours utiles tels que: Interval
, YearWeek
, YearQuarter
, et plus .
Java fournit la méthode statique System.currentTimeMillis()
. Et c'est un retour de valeur, donc c'est une bonne référence. Beaucoup d'autres classes acceptent un paramètre' timeInMillis ' qui est aussi long.
et beaucoup de gens trouvent plus facile d'utiliser la bibliothèque Joda Time pour faire des calculs sur les dates et les heures.
Quels types utiliser pour accomplir ceci en Java?
réponse : long
public class Stream {
public long startTime;
public long endTime;
public long getDuration() {
return endTime - startTime;
}
// I would add
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
endTime = System.currentTimeMillis();
}
}
Utilisation:
Stream s = ....
s.start();
// do something for a while
s.stop();
s.getDuration(); // gives the elapsed time in milliseconds.
C'est ma réponse directe à votre première question.
pour la dernière "note", je vous suggère D'utiliser le temps Joda. Il contient une classe intervalle adapté à ce que vous besoin.
Il est intéressant de noter que
- du Système.currentTimeMillis () n'a au mieux qu'une précision de milliseconde. À sa valeur peut être 16 ms sur certains systèmes de fenêtres. Il a un coût plus faible que les solutions de rechange < 200 ns. Système
- .nanoTime() est seulement micro-seconde précise sur la plupart des systèmes et peut sauter sur les systèmes windows de 100 microsecondes (I. e parfois il n'est pas aussi précis qu'il n'y paraît)
- Calendrier est un moyen très coûteux à calculer le temps. (je peux penser à l'exception de XMLGregorianCalendar) parfois, c'est la solution la plus appropriée, mais être conscient que vous ne devez que de longs intervalles de temps.
si vous écrivez une demande qui doit traiter des durées de temps, alors s'il vous plaît jeter un oeil à Joda-Time qui a Classe spécifiquement pour la manipulation des durées, intervalles , et des périodes. Votre méthode getDuration()
semble comme il pourrait retourner un Joda-Intervalle de temps:
DateTime start = new DateTime(2004, 12, 25, 0, 0, 0, 0);
DateTime end = new DateTime(2005, 1, 1, 0, 0, 0, 0);
public Interval getInterval() {
Interval interval = new Interval(start, end);
}
si vous préférez utiliser API calendrier "de Java, vous pouvez essayer ceci,
Date startingTime = Calendar.getInstance().getTime();
//later on
Date now = Calendar.getInstance().getTime();
long timeElapsed = now.getTime() - startingTime.getTime();
si vous obtenez vos horodateurs de System.currentTimeMillis()
, alors vos variables de temps devraient être longues.
Byte Stream Reader Elapsed Time for 23.7 MB is 96 secs
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingByteStream
{
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
{
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop()
{
this.stopTime = System.currentTimeMillis();
this.running = false;
}
public long getElapsedTime()
{
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
public long getElapsedTimeSecs()
{
long elapsed;
if (running)
{
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else
{
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
public static void main(String[] args) throws IOException
{
ElaspedTimetoCopyAFileUsingByteStream s = new ElaspedTimetoCopyAFileUsingByteStream();
s.start();
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("vowels.txt"); // 23.7 MB File
out = new FileOutputStream("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
}
}
[Elapsed Time for Byte Stream Reader][1]
**Character Stream Reader Elapsed Time for 23.7 MB is 3 secs**
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingCharacterStream
{
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
{
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop()
{
this.stopTime = System.currentTimeMillis();
this.running = false;
}
public long getElapsedTime()
{
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
public long getElapsedTimeSecs()
{
long elapsed;
if (running)
{
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else
{
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
public static void main(String[] args) throws IOException
{
ElaspedTimetoCopyAFileUsingCharacterStream s = new ElaspedTimetoCopyAFileUsingCharacterStream();
s.start();
FileReader in = null; // CharacterStream Reader
FileWriter out = null;
try {
in = new FileReader("vowels.txt"); // 23.7 MB
out = new FileWriter("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
}
}
[Elapsed Time for Character Stream Reader][2]
[1]: https://i.stack.imgur.com/hYo8y.png
[2]: https://i.stack.imgur.com/xPjCK.png
j'ai trouvé ce code utile pour chronométrer les choses:
public class Et {
public Et() {
reset();
}
public void reset() {
t0=System.nanoTime();
}
public long t0() {
return t0;
}
public long dt() {
return System.nanoTime()-t0();
}
public double etms() {
return etms(dt());
}
@Override public String toString() {
return etms()+" ms.";
}
public static double etms(long dt) {
return dt/1000000.; // 1_000_000. breaks cobertura
}
private Long t0;
}
utilisez ceci:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date d1 = format.parse(strStartTime);
Date d2 = format.parse(strEndTime);
long diff = d2.getTime() - d1.getTime();
long diffSeconds,diffMinutes,diffHours;
if (diff > 0) {
diffSeconds = diff / 1000 % 60;
diffMinutes = diff / (60 * 1000) % 60;
diffHours = diff / (60 * 60 * 1000);
}
else{
long diffpos = (24*((60 * 60 * 1000))) + diff;
diffSeconds = diffpos / 1000 % 60;
diffMinutes = diffpos / (60 * 1000) % 60;
diffHours = (diffpos / (60 * 60 * 1000));
}
(il est également important que par exemple si le startTime il est 23:00 et endTime 1:00 pour obtenir une durée de 2:00.)
la partie" else "peut l'obtenir correctement
j'ai construit une fonction de formatage basé sur des trucs que j'ai volé donc. J'avais besoin d'un moyen de "profiler" des trucs dans les messages de log, donc j'avais besoin d'un message de durée fixe.
public static String GetElapsed(long aInitialTime, long aEndTime, boolean aIncludeMillis)
{
StringBuffer elapsed = new StringBuffer();
Map<String, Long> units = new HashMap<String, Long>();
long milliseconds = aEndTime - aInitialTime;
long seconds = milliseconds / 1000;
long minutes = milliseconds / (60 * 1000);
long hours = milliseconds / (60 * 60 * 1000);
long days = milliseconds / (24 * 60 * 60 * 1000);
units.put("milliseconds", milliseconds);
units.put("seconds", seconds);
units.put("minutes", minutes);
units.put("hours", hours);
units.put("days", days);
if (days > 0)
{
long leftoverHours = hours % 24;
units.put("hours", leftoverHours);
}
if (hours > 0)
{
long leftoeverMinutes = minutes % 60;
units.put("minutes", leftoeverMinutes);
}
if (minutes > 0)
{
long leftoverSeconds = seconds % 60;
units.put("seconds", leftoverSeconds);
}
if (seconds > 0)
{
long leftoverMilliseconds = milliseconds % 1000;
units.put("milliseconds", leftoverMilliseconds);
}
elapsed.append(PrependZeroIfNeeded(units.get("days")) + " days ")
.append(PrependZeroIfNeeded(units.get("hours")) + " hours ")
.append(PrependZeroIfNeeded(units.get("minutes")) + " minutes ")
.append(PrependZeroIfNeeded(units.get("seconds")) + " seconds ")
.append(PrependZeroIfNeeded(units.get("milliseconds")) + " ms");
return elapsed.toString();
}
private static String PrependZeroIfNeeded(long aValue)
{
return aValue < 10 ? "0" + aValue : Long.toString(aValue);
}
et une classe d'essai:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import junit.framework.TestCase;
public class TimeUtilsTest extends TestCase
{
public void testGetElapsed()
{
long start = System.currentTimeMillis();
GregorianCalendar calendar = (GregorianCalendar) Calendar.getInstance();
calendar.setTime(new Date(start));
calendar.add(Calendar.MILLISECOND, 610);
calendar.add(Calendar.SECOND, 35);
calendar.add(Calendar.MINUTE, 5);
calendar.add(Calendar.DAY_OF_YEAR, 5);
long end = calendar.getTimeInMillis();
assertEquals("05 days 00 hours 05 minutes 35 seconds 610 ms", TimeUtils.GetElapsed(start, end, true));
}
}