System.currentTimeMillis () vs new Date () vs. Calendar.getInstance (). GetTime ()

239

En Java, quelles sont les implications en termes de performances et de ressources de l'utilisation

System.currentTimeMillis() 

contre.

new Date() 

contre.

Calendar.getInstance().getTime()

Si je comprends bien, System.currentTimeMillis()est le plus efficace. Cependant, dans la plupart des applications, cette valeur longue devrait être convertie en une date ou un objet similaire pour faire quelque chose de significatif pour les humains.

Vihung
la source

Réponses:

242

System.currentTimeMillis()est évidemment le plus efficace car il ne crée même pas d'objet, mais new Date()n'est en réalité qu'une mince enveloppe sur une longue, donc il n'est pas loin derrière. Calendar, d'autre part, est relativement lent et très complexe, car il doit faire face à la complexité considérable et à toutes les bizarreries inhérentes aux dates et aux heures (années bissextiles, heure d'été, fuseaux horaires, etc.).

C'est généralement une bonne idée de ne traiter que de longs horodatages ou Dateobjets dans votre application, et de ne les utiliser que Calendarlorsque vous avez réellement besoin d'effectuer des calculs de date / heure ou de formater des dates pour les afficher à l'utilisateur. Si vous devez faire beaucoup de cela, utiliser Joda Time est probablement une bonne idée, pour une interface plus propre et de meilleures performances.

Michael Borgwardt
la source
2
Quelle est la différence entre timestamp et currentMillis?
pinkpanther
1
@pinkpanther: "timestamp" est normalement utilisé pour décrire un entier / long qui décrit un point dans le temps lorsqu'il est interprété comme les secondes ou millisecondes depuis un "début d'époque". En d'autres termes, currentTimeMillis () renvoie un horodatage.
Michael Borgwardt
43

En regardant le JDK, le constructeur le plus interne pour Calendar.getInstance()ceci:

public GregorianCalendar(TimeZone zone, Locale aLocale) {
    super(zone, aLocale);
    gdate = (BaseCalendar.Date) gcal.newCalendarDate(zone);
    setTimeInMillis(System.currentTimeMillis());
}

donc il fait déjà automatiquement ce que vous proposez. Le constructeur par défaut de Date contient ceci:

public Date() {
    this(System.currentTimeMillis());
}

Il n'est donc vraiment pas nécessaire d'obtenir l'heure système spécifiquement, sauf si vous voulez faire un peu de calcul avec avant de créer votre objet Calendrier / Date avec. Je dois également recommander joda-time pour remplacer les propres classes de calendrier / date de Java si votre but est de travailler beaucoup avec les calculs de date.

Esko
la source
22

Si vous UTILISEZ une date, je vous conseille fortement d'utiliser jodatime, http://joda-time.sourceforge.net/ . Utilisation System.currentTimeMillis()pour les champs qui sont dates semble être une très mauvaise idée car vous vous retrouverez avec beaucoup de code inutile.

La date et le calendrier sont sérieusement bousculés, et le calendrier est certainement le pire interprète de tous.

Je vous conseille d'utiliser System.currentTimeMillis()lorsque vous utilisez réellement des millisecondes, par exemple comme ceci

 long start = System.currentTimeMillis();
    .... do something ...
 long elapsed = System.currentTimeMillis() -start;
krosenvold
la source
28
Je voulais commenter cela parce que votre exemple est exactement l'une des choses pour lesquelles vous ne devriez PAS utiliser System.currentTimeMillis () pour; ce n'est pas une source d'horloge monotone, vous ne pouvez donc pas calculer de manière fiable le temps écoulé avec elle. Si l'horloge système est modifiée pendant l'exécution du code que vous chronométrez, vous obtiendrez des résultats étranges (par exemple négatifs). Utilisez plutôt System.nanoTime (), qui est monotone si le système sous-jacent prend en charge une telle source d'horloge (voir bugs.java.com/bugdatabase/view_bug.do?bug_id=6458294 )
rem
System.currentTimeMillis lui-même n'est pas affecté par le fuseau horaire. La modification de l'heure système affectera System.nanotime de la même manière que System.currentTimeMillis
Viktor
12

Je préfère utiliser la valeur renvoyée par System.currentTimeMillis()pour toutes sortes de calculs et utiliser uniquement Calendarou Datesi j'ai vraiment besoin d'afficher une valeur lue par les humains. Cela empêchera également 99% de vos bogues d'heure d'été. :)

Bombe
la source
12

Sur ma machine, j'ai essayé de le vérifier. Mon résultat:

Calendar.getInstance (). GetTime () (* 1000000 fois) = 402ms
new Date (). getTime (); (* 1000000 fois) = 18 ms
System.currentTimeMillis () (* 1000000 fois) = 16 ms

N'oubliez pas GC (si vous utilisez Calendar.getInstance()ou new Date())

Puzirki
la source
1
me demande s'il y aura une différence si de nombreux threads appellent la même chose entre d'autres traitements
tgkprog
7

Selon votre application, vous voudrez peut-être envisager d'utiliser à la System.nanoTime()place.

MykennaC
la source
Pourquoi, sa question portait sur les ressources et les performances, nanoTime () utilise plus de ressources
WolfmanDragon
Je l'ai mentionné parce que c'est une option que personne d'autre n'a suggérée. L'affiche ne précisait pas de plateforme. Le bogue SDN 6876279 suggère que currentTimeMillis () et nanoTime () prennent à peu près la même chose dans certaines versions de JDK. L'affiche n'a pas non plus précisé leurs besoins en matière d'exactitude, pour lesquels la liste originale peut être insuffisante.
MykennaC
4
Aussi tard que cela puisse être, tous les exemples de la question ont une notion absolue de l'heure qu'il est, par exemple. 1 348 770 313 071 millis depuis le début de l'époque Unix. Le temps qui nanoTimerevient est relatif (généralement au début du programme) et serait insensé si vous tentiez de le transformer en date.
Dunes
oui mais vous pouvez stocker currentTimeilli et nano dans du code statique au démarrage du programme, puis les utiliser comme décalages pour obtenir un nano précis de milli en utilisant un double var = currentTimeStart - nanoTimeStart + nanoTimeNow
tgkprog
3

J'ai essayé ceci:

        long now = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            new Date().getTime();
        }
        long result = System.currentTimeMillis() - now;

        System.out.println("Date(): " + result);

        now = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            System.currentTimeMillis();
        }
        result = System.currentTimeMillis() - now;

        System.out.println("currentTimeMillis(): " + result);

Et le résultat a été:

Date (): 199

currentTimeMillis (): 3

wiji
la source
4
Il s'agit d'une micro-référence et vous devez faire attention aux résultats que vous obtenez. Jetez un œil à stackoverflow.com/questions/504103/… .
Axel
1
Ce benchmark n'est pas significatif, ou mieux, il montre que le système d'exploitation sous Java est important. J'ai exécuté le même benchmark dans une boucle des dizaines de fois (en déplaçant l'initialisation de "maintenant" et "résultat" hors de la boucle), et j'ai eu de jolies différences à chaque exécution: Date (): 322 à 330; currentTimeMillis (): 319 à 322. Sur d'autres exécutions, j'ai eu Date (): 312 à 318; currentTimeMillis (): 324 à 335. Donc, à mon humble avis, ils sont assez équivalents, sur des cas réels (en regardant également la source de Date). JFYI, j'ai utilisé Java7 sur Ubuntu.
Sampisa
0

System.currentTimeMillis() est évidemment le plus rapide car ce n'est qu'un appel de méthode et aucun garbage collector n'est requis.

Ramón
la source
14
Votre réponse n'a aucune valeur car elle n'est qu'un sous-ensemble de la réponse précédemment approuvée. Vous devriez essayer de ne pas répondre de cette manière, surtout en ne considérant pas qu'il s'agit d'une très vieille question avec une réponse de qualité déjà existante.
Nicklas Gnejs Eriksson le
1
Deuxièmement, le ramasse-miettes n'est de toute façon pas requis pour les objets à court terme dans l'espace Eden.
Niels Bech Nielsen