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

239

En Java, ¿cuáles son las implicaciones de rendimiento y recursos del uso

System.currentTimeMillis() 

vs.

new Date() 

vs.

Calendar.getInstance().getTime()

Según tengo entendido, System.currentTimeMillis()es el más eficiente. Sin embargo, en la mayoría de las aplicaciones, ese valor largo necesitaría convertirse a una Fecha o algún objeto similar para hacer algo significativo para los humanos.

Vihung
fuente

Respuestas:

242

System.currentTimeMillis()obviamente es el más eficiente, ya que ni siquiera crea un objeto, sino new Date()que en realidad es solo una envoltura delgada de un largo, por lo que no está muy lejos. CalendarPor otro lado, es relativamente lento y muy complejo, ya que tiene que lidiar con la considerable complejidad y todas las rarezas inherentes a las fechas y horas (años bisiestos, horario de verano, zonas horarias, etc.).

Por lo general, es una buena idea tratar solo con marcas de tiempo u Dateobjetos largos dentro de su aplicación, y solo usarlos Calendarcuando realmente necesite realizar cálculos de fecha / hora, o formatear fechas para mostrarlos al usuario. Si tiene que hacer mucho de esto, usar Joda Time es probablemente una buena idea, para una interfaz más limpia y un mejor rendimiento.

Michael Borgwardt
fuente
2
¿Cuál es la diferencia entre timestamp y currentMillis?
pinkpanther
1
@pinkpanther: "marca de tiempo" se usa normalmente para describir un número entero / largo que describe un punto en el tiempo cuando se interpreta como los segundos o milisegundos desde un "inicio de época". En otras palabras, currentTimeMillis () devuelve una marca de tiempo.
Michael Borgwardt
43

Mirando el JDK, el constructor más interno para Calendar.getInstance()tiene esto:

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

entonces ya hace automáticamente lo que sugieres. El constructor predeterminado de Date contiene esto:

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

Por lo tanto, realmente no es necesario obtener la hora del sistema específicamente a menos que desee hacer algunos cálculos matemáticos antes de crear su objeto Calendario / Fecha. También tengo que recomendar joda-time para usar como reemplazo de las propias clases de calendario / fecha de Java si su propósito es trabajar mucho con los cálculos de fecha.

Esko
fuente
22

Si está USANDO una fecha, le recomiendo que use jodatime, http://joda-time.sourceforge.net/ . Usar System.currentTimeMillis()campos que son fechas parece una muy mala idea porque terminarás con un montón de código inútil.

Tanto la fecha como el calendario están seriamente alterados, y el calendario es definitivamente el peor de todos.

Le aconsejaría que lo use System.currentTimeMillis()cuando realmente esté operando con milisegundos, por ejemplo, así

 long start = System.currentTimeMillis();
    .... do something ...
 long elapsed = System.currentTimeMillis() -start;
krosenvold
fuente
28
Quería comentar sobre esto porque su ejemplo es exactamente una de las cosas para las que NO debería usar System.currentTimeMillis (); no es una fuente de reloj monótono, por lo que no puede calcular de manera confiable el tiempo transcurrido con él. Si se cambia el reloj del sistema mientras se ejecuta el código que está sincronizando, obtendrá resultados extraños (por ejemplo, negativos). En su lugar, use System.nanoTime (), que es monótono si el sistema subyacente admite dicha fuente de reloj (consulte bugs.java.com/bugdatabase/view_bug.do?bug_id=6458294 )
rem
System.currentTimeMillis en sí no se ve afectado por la zona horaria. Cambiar la hora del sistema afectará System.nanotime de la misma manera que System.currentTimeMillis
Viktor
12

Prefiero usar el valor devuelto por System.currentTimeMillis()para todo tipo de cálculos y solo uso Calendaro Datesi realmente necesito mostrar un valor que sea leído por humanos. Esto también evitará el 99% de sus errores de horario de verano. :)

Bombe
fuente
12

En mi máquina intenté comprobarlo. Mi resultado:

Calendar.getInstance (). GetTime () (* 1000000 veces) = 402ms
nueva Fecha (). getTime (); (* 1000000 veces) = 18 ms
System.currentTimeMillis () (* 1000000 veces) = 16 ms

No te olvides de GC (si usas Calendar.getInstance()o new Date())

Puzirki
fuente
1
me pregunto si habrá alguna diferencia si muchos hilos llaman lo mismo entre otros procesos
tgkprog
7

Dependiendo de su aplicación, puede considerar usar en su System.nanoTime()lugar.

MykennaC
fuente
Por qué, su pregunta era sobre recursos y rendimiento, nanoTime () usa más recursos
WolfmanDragon
Lo mencioné porque es una opción que nadie más sugirió. El póster no especificaba una plataforma. El error 6876279 de SDN sugiere que currentTimeMillis () y nanoTime () toman aproximadamente lo mismo en algunas versiones de JDK. El póster tampoco especificó sus necesidades de precisión, por lo que la lista original puede ser inadecuada.
MykennaC
44
Tarde como puede ser, todos los ejemplos en la pregunta tienen una noción absoluta de qué hora es, por ejemplo. 1,348,770,313,071 milis desde el comienzo de la época de Unix. El tiempo que nanoTimeregresa es relativo (generalmente al inicio del programa) y no tendría sentido si intentara convertirlo en una fecha.
Dunas
sí, pero podría almacenar currentTimeilli y nano en algún código estático al inicio del programa, luego usarlos como compensaciones para obtener un nano preciso de milli usando un doble var = currentTimeStart - nanoTimeStart + nanoTimeNow
tgkprog
3

Intenté esto:

        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);

Y el resultado fue:

Fecha (): 199

currentTimeMillis (): 3

wiji
fuente
44
Este es un micro punto de referencia y debe tener cuidado de confiar en los resultados que obtiene. Eche un vistazo a stackoverflow.com/questions/504103/… .
Axel
1
Este punto de referencia no es significativo, o mejor, muestra que el sistema operativo en Java sí importa. Ejecuté el mismo punto de referencia en un bucle una docena de veces (moviendo la inicialización de "ahora" y "resultado" fuera del bucle), y tuve diferencias lindas en cada ejecución: Fecha (): 322 a 330; currentTimeMillis (): 319 a 322. En algunas otras ejecuciones tuve Date (): 312 a 318; currentTimeMillis (): 324 a 335. Por lo tanto, en mi humilde opinión, son bastante equivalentes, en casos reales (también mirando la fuente de Date). JFYI, usé Java7 en Ubuntu.
Sampisa
0

System.currentTimeMillis() obviamente es el más rápido porque es solo una llamada al método y no se requiere recolector de basura.

Ramón
fuente
14
Su respuesta no tiene valor ya que es solo un subconjunto de la respuesta aprobada previamente. Debe intentar no responder de esta manera, especialmente sin considerar que es una pregunta muy antigua con una respuesta de calidad ya existente.
Nicklas Gnejs Eriksson
1
En segundo lugar, el recolector de basura no es necesario para objetos a corto plazo en el espacio Eden de todos modos.
Niels Bech Nielsen