360 votes

Comment mesurer le temps écoulé en Java ?

Je veux avoir quelque chose comme ça :

public class Stream
{
    public startTime;
    public endTime;

    public getDuration()
    {
        return startTime - endTime;
    }
}

Il est également important que, par exemple, si l'heure de début est 23:00 et l'heure de fin 1:00, la durée soit de 2:00.

Quels types utiliser pour réaliser cela en Java ?

1 votes

1 votes

El Question liée n'est pas un doublon. Le titre de cette question est trompeur. Le contenu de cette question porte sur l'accès à l'heure actuelle à partir de l'horloge de l'ordinateur. Les réponses impliquent ` System.currentTimeMillis()` et System.nanoTime() . Cette question se concentre ici sur le calcul du temps écoulé entre deux moments, sans tenir compte de la récupération de l'heure actuelle.

708voto

Kevin Bourrillion Points 19677

Malheureusement, aucune des dix réponses postées jusqu'à présent n'est tout à fait juste.

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 cela ne vous dérange pas que votre résultat soit faux.

Le but de nanoTime est de mesurer écoulé temps, et le but de currentTimeMillis est de mesurer horloge murale temps. Vous ne pouvez pas utiliser l'une pour l'autre. La raison en est qu'aucune horloge d'ordinateur n'est parfaite ; elle dérive toujours et doit être corrigée de temps en temps. Cette correction peut se faire manuellement ou, dans le cas de la plupart des machines, il existe un processus qui fonctionne et apporte continuellement de petites corrections à l'horloge du système ("horloge murale"). Ces corrections ont tendance à être fréquentes. Une autre correction de ce type se produit lorsqu'il y a une seconde intercalaire.

Depuis nanoTime Le but de l'appareil est de mesurer le temps écoulé, il n'est pas affecté par ces petites corrections. C'est ce que vous voulez utiliser. Tous les chronométrages en cours avec currentTimeMillis sera décalé, voire même négatif.

Vous pouvez dire, "cela ne semble pas avoir beaucoup d'importance", ce à quoi je réponds, peut-être pas, mais globalement, un code correct n'est-il pas mieux qu'un code incorrect ? D'ailleurs, nanoTime est plus court à taper de toute façon.

Les avertissements publiés précédemment concernant nanoTime n'ayant généralement qu'une précision de l'ordre de la microseconde sont valables. De plus, l'invocation de cette fonction peut prendre plus d'une microseconde entière, selon les circonstances (tout comme l'autre), donc ne vous attendez pas à chronométrer correctement de très très petits intervalles.

4 votes

En fait, j'ai besoin de mesurer des durées de plusieurs minutes ou parfois même d'une heure, quelque chose comme ça. Y a-t-il des problèmes de performance entre nanotime et currentmiliseconds ?

4 votes

Se méfier de nanoTime dans les environnements multi-core

1 votes

@jasonk pouvez-vous clarifier ?

235voto

Pascal Thivent Points 295221

Quels types utiliser pour réaliser cela en Java ?

La réponse courte est long . Maintenant, plus sur la façon de mesurer...

System.currentTimeMillis()

La manière "traditionnelle" de procéder est en effet d'utiliser [System.currentTimeMillis()](http://java.sun.com/javase/6/docs/api/java/lang/System.html#currentTimeMillis()) :

long startTime = System.currentTimeMillis();
// ... do something ...
long estimatedTime = System.currentTimeMillis() - startTime;

o.a.c.l.t.StopWatch

Notez que Commons Lang a un Chronomètre qui peut être utilisée pour mesurer le temps d'exécution en millisecondes. Elle possède des méthodes comme [split()](http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/time/StopWatch.html#split()) , [suspend()](http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/time/StopWatch.html#suspend()) , [resume()](http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/time/StopWatch.html#resume()) etc. qui permettent de prendre des mesures à différents moments de l'exécution et que vous pouvez trouver pratiques. Jetez-y un coup d'œil.

System.nanoTime()

Vous pouvez préférer utiliser System.nanoTime() si vous recherchez des mesures extrêmement précises du temps écoulé. Extrait de sa 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 d'occurrences, temps d'exécution moyen, min, max, etc.) pour tout code intervenant 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();

Vérifiez cet article sur www.javaperformancetunning.com pour une belle introduction.

Utilisation de la POA

Enfin, si vous ne voulez pas encombrer votre code avec ces mesures (ou si vous ne pouvez pas modifier le code existant), alors la POA serait une arme parfaite. Je ne vais pas en discuter très profondément mais je voulais au moins le mentionner.

Ci-dessous, un aspect très simple 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 des raccourcis pourrait être facilement adaptée pour surveiller n'importe quelle méthode en fonction du nom de la classe, du nom du paquet, du nom de la méthode ou de toute combinaison de ces éléments. La mesure est vraiment un cas d'utilisation parfait pour la POA.

42voto

GHad Points 4131

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 dans le format que vous souhaitez, avec un calendrier par exemple.

Salutations, GHad

2 votes

+1 pour le TimeUnit mention. Je ne savais pas qu'il existait (pourquoi n'est-il pas dans le paquet `java.util' ?).

0 votes

@Oscar Peut-être que M. Lea a considéré que cela faisait partie de l'API concurrente.

0 votes

TimeUnit existe depuis Java 1.5, mais a été étendu dans Java 1.6. C'est un enum très utile pour travailler.

23voto

David Bliss Points 91

Si le but est simplement d'imprimer des informations de chronométrage grossières dans les journaux de votre programme, alors la solution facile pour les projets Java n'est pas d'écrire vos propres classes de chronomètre ou de minuterie, mais d'utiliser simplement la classe [org.apache.commons.lang.time.StopWatch](https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/time/StopWatch.html#toSplitString()) qui fait partie de 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);

0 votes

La plupart des enregistreurs prennent également en charge les horodatages dans le cadre de la sortie de l'enregistrement.

2 votes

@James McMahon. Oui, mais ces horodatages indiquent le temps actuel, et non le temps cumulé d'une tâche donnée.

1 votes

Notez que StopWatch utilise System.currentTimeMillis() dans son implémentation.

7voto

Andreas_D Points 64111

Java fournit la méthode statique System.currentTimeMillis() . Et cela renvoie une valeur longue, donc c'est une bonne référence. Beaucoup d'autres classes acceptent un paramètre 'timeInMillis' qui est également long.

Et beaucoup de gens trouvent qu'il est plus facile d'utiliser les Joda Time bibliothèque pour effectuer des calculs sur les dates et les heures.

0 votes

+1 pour avoir mentionné joda time. qu'est-il arrivé au portage en java proprement dit ? jsr310 ?

0 votes

@Bedwyr : il n'est malheureusement pas encore terminé. Peut-être Java8.

0 votes

@BalusC hmm - peut-être qu'ils peuvent trouver le temps de le faire maintenant que les fermetures sont en place et que tout est retardé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X