¿Hay cronómetro en Java?

107

¿Hay cronómetro en Java? En Google solo encuentro códigos de cronómetros que no funcionan, siempre devuelven 0 milisegundos.

Este código que encontré no funciona pero no veo por qué.

public class StopWatch {

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


  //elaspsed time in milliseconds
  public long getElapsedTime() {
    long elapsed;
    if (running) {
      elapsed = (System.currentTimeMillis() - startTime);
    } else {
      elapsed = (stopTime - startTime);
    }
    return elapsed;
  }


  //elaspsed time in seconds
  public long getElapsedTimeSecs() {
    long elapsed;
    if (running) {
      elapsed = ((System.currentTimeMillis() - startTime) / 1000);
    } else {
      elapsed = ((stopTime - startTime) / 1000);
    }
    return elapsed;
  }
}
user1007522
fuente
10
¿Y cómo determina que no funcionó? (quizás esté midiendo algo que requiere menos tiempo para ejecutarse que la precisión de System.currentTimeMillis ())
nos
5
Publique
2
Solo quería señalar que esta es una de las preguntas del libro de texto en "Introducción a la programación de Java, versión completa (novena edición)".
Sam
2
No lo use currentTimeMillis()para producción, ya que está vinculado a la fecha / hora del sistema y no se garantiza que sea monótono (por ejemplo, puede obtener un tiempo transcurrido negativo). Para medir el uso del tiempo nanoTime(), se garantiza que es monótono y está diseñado exactamente para medir. Ver docs.oracle.com/javase/8/docs/api/java/lang/…
Nikita Bosik

Respuestas:

90

Usa la Stopwatchclase de Guava .

Objeto que mide el tiempo transcurrido en nanosegundos. Es útil medir el tiempo transcurrido usando esta clase en lugar de llamadas directas a System.nanoTime()por algunas razones:

  • Se puede sustituir una fuente de tiempo alternativa, por razones de prueba o rendimiento.
  • Según lo documentado por nanoTime, el valor devuelto no tiene un significado absoluto y solo se puede interpretar como relativo a otra marca de tiempo devuelta por nanoTime en un momento diferente. El cronómetro es una abstracción más eficaz porque expone solo estos valores relativos, no los absolutos.
Stopwatch stopwatch = Stopwatch.createStarted();
doSomething();
stopwatch.stop(); // optional

long millis = stopwatch.elapsed(TimeUnit.MILLISECONDS);

log.info("that took: " + stopwatch); // formatted string like "12.3 ms"
método de ayuda
fuente
2
Falta el cronómetro de guayabas getStartTime(), falta el apache isRunning()ahhhh
A Kra
3
@ToKra ¿Qué harías con la hora de inicio de todos modos? Dado que es nano hora, no puede usarlo para nada significativo de todos modos, como se describe en los documentos.
Trejkaz
1
Ahora usa esto para obtener los milisegundos: long stopWatch = stopWatch.elapsed (TimeUnit.MILLISECONDS);
PHPGuru
¿Qué versión de guayaba es? Usé 1.8 y no encontré la clase Cronómetro
Laser Infinite
58

Ahora puedes probar algo como:

Instant starts = Instant.now();
Thread.sleep(10);
Instant ends = Instant.now();
System.out.println(Duration.between(starts, ends));

La salida está en ISO 8601.

Valtoni Boaventura
fuente
1
Rápido y fácil, ¡muchas gracias! Ayuda a realizar un seguimiento de la duración de la tarea desde el principio.
ndm13
¿Qué pasa si cambia la hora del sistema durante la suspensión?
Peteter
1
@Peteter es solo un ejemplo. Si está en una caja Linux, debe lidiar con el reloj de hardware y el reloj administrado por el núcleo. Si cambia el reloj del hardware, ninguno se verá afectado, pero en el reloj administrado por el kernel tendrá problemas: Instant.now () obtiene la hora del sistema y mostrará un intervalo de tiempo incorrecto.
Valtoni Boaventura
Ni siquiera sabía que funcionaba en Android. Bueno saber :)
Valtoni Boaventura
Sin olvidar java.time.Instant es inmutable y seguro para subprocesos :)
Amos Kosgei
38

Spring proporciona una org.springframework.util.StopWatchclase elegante (módulo de núcleo de resorte).

StopWatch stopWatch = new StopWatch();
stopWatch.start();
     // Do something
stopWatch.stop();
     System.out.println(stopWatch.getTotalTimeMillis());
Larsen
fuente
8

Utilice System.currentTimeMillis()para obtener la hora de inicio y la hora de finalización y calcular la diferencia.

class TimeTest1 {
  public static void main(String[] args) {

    long startTime = System.currentTimeMillis();

    long total = 0;
    for (int i = 0; i < 10000000; i++) {
      total += i;
    }

    long stopTime = System.currentTimeMillis();
    long elapsedTime = stopTime - startTime;
    System.out.println(elapsedTime);
  }
} 

Más información en este tutorial

user2374612
fuente
Como se dijo en otra parte, currentTimeMillis () está vinculado a la fecha / hora del sistema y no se garantiza que sea monótono (por ejemplo, puede obtener un tiempo transcurrido negativo).
oligofren
8

El código no funciona porque la variable transcurrida en getElapsedTimeSecs()no es un floato double.

asferir
fuente
7

No hay una utilidad de cronómetro incorporada, pero a partir de JSR-310 (Java 8 Time) puede hacer esto simplemente.

ZonedDateTime now = ZonedDateTime.now();
// Do stuff
long seconds = now.until(ZonedDateTime.now(), ChronoUnit.SECONDS);

No he evaluado esto correctamente, pero supongo que usar el cronómetro de Guava es más efectivo.

matsa
fuente
3

Clase de cronómetro simple y lista para usar:

import java.time.Duration;
import java.time.Instant;

public class StopWatch {

    Instant startTime, endTime;
    Duration duration;
    boolean isRunning = false;

    public void start() {
        if (isRunning) {
            throw new RuntimeException("Stopwatch is already running.");
        }
        this.isRunning = true;
        startTime = Instant.now();
    }

    public Duration stop() {
        this.endTime = Instant.now();
        if (!isRunning) {
            throw new RuntimeException("Stopwatch has not been started yet");
        }
        isRunning = false;
        Duration result = Duration.between(startTime, endTime);
        if (this.duration == null) {
            this.duration = result;
        } else {
            this.duration = duration.plus(result);
        }

        return this.getElapsedTime();
    }

    public Duration getElapsedTime() {
        return this.duration;
    }

    public void reset() {
        if (this.isRunning) {
            this.stop();
        }
        this.duration = null;
    }
}

Uso:

StopWatch sw = new StopWatch();
sw.start();
    // doWork()
sw.stop();
System.out.println( sw.getElapsedTime().toMillis() + "ms");
Jonas_Hess
fuente
3

use: com.google.common.base.Stopwatch, es simple y fácil.

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>

ejemplo:

Stopwatch stopwatch = new Stopwatch();
stopwatch.start();

"Do something"

logger.debug("this task took " + stopwatch.stop().elapsedTime(TimeUnit.MILLISECONDS) + " mills");

esta tarea tomó 112 molinos

Luke_P
fuente
2

prueba esto

import java.awt.event.*;

import java.awt.*;

import javax.swing.*;

public class millis extends JFrame implements ActionListener, Runnable
    {

     private long startTime;
     private final static java.text.SimpleDateFormat timerFormat = new java.text.SimpleDateFormat("mm : ss.SSS");
     private final JButton startStopButton= new JButton("Start/stop");
     private Thread updater;
     private boolean isRunning= false;
     private final Runnable displayUpdater= new Runnable()
         {
         public void run()
             {
             displayElapsedTime(System.currentTimeMillis() - millis.this.startTime);
         }
     };
     public void actionPerformed(ActionEvent ae)
         {
         if(isRunning)
             {
             long elapsed= System.currentTimeMillis() - startTime;
             isRunning= false;
             try
                 {
                 updater.join();
                 // Wait for updater to finish
             }
             catch(InterruptedException ie) {}
             displayElapsedTime(elapsed);
             // Display the end-result
         }
         else
             {
             startTime= System.currentTimeMillis();
             isRunning= true;
             updater= new Thread(this);
             updater.start();
         }
     }
     private void displayElapsedTime(long elapsedTime)
         {
         startStopButton.setText(timerFormat.format(new java.util.Date(elapsedTime)));
     }
     public void run()
         {
         try
             {
             while(isRunning)
                 {
                 SwingUtilities.invokeAndWait(displayUpdater);
                 Thread.sleep(50);
             }
         }
         catch(java.lang.reflect.InvocationTargetException ite)
             {
             ite.printStackTrace(System.err);
             // Should never happen!
         }
         catch(InterruptedException ie) {}
         // Ignore and return!
     }
     public millis()
         {
         startStopButton.addActionListener(this);
         getContentPane().add(startStopButton);
         setSize(100,50);
         setVisible(true);
     }
     public static void main(String[] arg)
         {
         new Stopwatch().addWindowListener(new WindowAdapter()
             {
             public void windowClosing(WindowEvent e)
                 {
                 System.exit(0);
             }
         });
         millis s=new millis();
         s.run();
     }
}
Andrewsi
fuente
1
Como se dijo en otra parte, currentTimeMillis () está vinculado a la fecha / hora del sistema y no se garantiza que sea monótono (por ejemplo, puede obtener un tiempo transcurrido negativo).
oligofren
2

Prueba esto:

/*
 * calculates elapsed time in the form hrs:mins:secs
 */
public class StopWatch
{ 
    private Date startTime;

    public void startTiming()
    {
        startTime = new Date();
    }

    public String stopTiming()
    {
        Date stopTime = new Date();
        long timediff = (stopTime.getTime() - startTime.getTime())/1000L;
        return(DateUtils.formatElapsedTime(timediff));
    }

}

Utilizar:

StopWatch sw = new StopWatch();
...
sw.startTiming();
...
String interval = sw.stopTiming();
Oke Uwechue
fuente
2
DateUtils es parte de Apache Commons, ¿por qué no usar su StopWatch?
Bill Effin Murray
En la mayoría de los casos, usará alguna biblioteca común como se menciona en otras respuestas (Apache Commons, por ejemplo). Incluso puede llevarse solo partes de la biblioteca si no lo necesita todo.
guyarad
2

Prueba esto.

public class StopWatch { 

      private long startTime = 0;
      private long stopTime = 0;

      public StopWatch()
      {
            startTime = System.currentTimeMillis();
      }

      public void start() {
        startTime = System.currentTimeMillis();
      }

      public void stop() {
        stopTime = System.currentTimeMillis();
        System.out.println("StopWatch: " + getElapsedTime() + " milliseconds.");
        System.out.println("StopWatch: " + getElapsedTimeSecs() + " seconds.");
      }

      /**
       * @param process_name
       */
      public void stop(String process_name) {
            stopTime = System.currentTimeMillis();
            System.out.println(process_name + " StopWatch: " + getElapsedTime() + " milliseconds.");
            System.out.println(process_name + " StopWatch: " + getElapsedTimeSecs() + " seconds.");
      }      

      //elaspsed time in milliseconds
      public long getElapsedTime() {
          return stopTime - startTime;
      }

      //elaspsed time in seconds
      public double getElapsedTimeSecs() {
        double elapsed;
          elapsed = ((double)(stopTime - startTime)) / 1000;
        return elapsed;
      }
} 

Uso:

StopWatch watch = new StopWatch();
// do something
watch.stop();

Consola:

StopWatch: 143 milliseconds.
StopWatch: 0.143 seconds.
Kansas
fuente
Aunque esto puede ser o no lo que se pedía en la pregunta, su respuesta me ayudó con mi problema. Gracias.
Toiletduck
currentTimeMillis()está vinculado a la fecha / hora del sistema y no se garantiza que sea monótono (por ejemplo, puede obtener un tiempo transcurrido negativo).
oligofren
Si decides construir el tuyo propio, utilízalo System.nanoTime()para obtener siempre los resultados correctos.
oligofren
2

Performetrics proporciona una clase de cronómetro conveniente, justo de la manera que necesita. Puede medir el tiempo del reloj de pared y más: también mide el tiempo de la CPU (tiempo del usuario y tiempo del sistema) si lo necesita. Es pequeño, gratuito y se puede descargar desde Maven Central. Puede encontrar más información y ejemplos aquí: https://obvj.net/performetrics

Stopwatch sw = new Stopwatch();
sw.start();

// Your code

sw.stop();
sw.printStatistics(System.out);

// Sample output:
// +-----------------+----------------------+--------------+
// | Counter         |         Elapsed time | Time unit    |
// +-----------------+----------------------+--------------+
// | Wall clock time |             85605718 | nanoseconds  |
// | CPU time        |             78000500 | nanoseconds  |
// | User time       |             62400400 | nanoseconds  |
// | System time     |             15600100 | nanoseconds  |
// +-----------------+----------------------+--------------+

Puede convertir las métricas a cualquier unidad de tiempo (nanosegundos, milisegundos, segundos, etc.)

PD: soy el autor de la herramienta.

Oswaldo Junior
fuente
1

Prueba esto.

Solución Java Stopwatch completamente funcional

Aquí obtendrá una solución totalmente funcional.

Solo un fragmento de la solución vinculada anteriormente:

Puede crear una clase como el código siguiente y usar el método de inicio y parada de esta clase antes y después de la sección de código, desea medir el tiempo necesario.

public class Stopwatch{
  private long startTime;
  private long stopTime;

  /**
   starting the stop watch.
  */
  public void start(){
        startTime = System.nanoTime();
  }

  /**
   stopping the stop watch.
  */
  public void stop()
  {     stopTime = System.nanoTime(); }

  /**
  elapsed time in nanoseconds.
  */
  public long time(){
        return (stopTime - startTime);
  }

  public String toString(){
      return "elapsed time: " + time() + " nanoseconds.";
  }

}

Gracias.

Sukriti Sarkar
fuente
1
Si bien este enlace puede responder a la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden dejar de ser válidas si cambia la página enlazada.
AS Mackay
Gracias @ASMackay por tu sugerencia. Estoy completamente de acuerdo contigo.
Sukriti Sarkar