Existe um cronômetro em Java?

107

Existe um cronômetro em Java? No google, só encontro códigos de cronômetros que não funcionam - eles sempre retornam 0 milissegundos.

Este código que encontrei não funciona, mas não vejo 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
fonte
10
E como você determinou que não funcionou? (talvez você esteja medindo algo que leva menos tempo para executar do que a precisão de System.currentTimeMillis ())
nos
5
Por favor, poste o código de como você está testando esta classe ...
DXTR66
2
Só queria observar que esta é uma das perguntas do livro didático em "Introdução à programação Java, versão abrangente (9ª edição)".
Sam
2
Não use currentTimeMillis()para produção, pois está vinculado à data / hora do sistema e não é garantido que seja monótono (por exemplo, você pode obter o tempo decorrido negativo). Para medir o tempo de uso nanoTime()- é garantido ser monótono e destinado exatamente para fins de medição. Consulte docs.oracle.com/javase/8/docs/api/java/lang/…
Nikita Bosik

Respostas:

90

Use a Stopwatchclasse de Guava .

Um objeto que mede o tempo decorrido em nanossegundos. É útil medir o tempo decorrido usando esta classe em vez de chamadas diretas para System.nanoTime()por alguns motivos:

  • Uma fonte de tempo alternativa pode ser substituída, por motivos de teste ou desempenho.
  • Conforme documentado pelo nanoTime, o valor retornado não tem significado absoluto e só pode ser interpretado como relativo a outro carimbo de data / hora retornado pelo nanoTime em um momento diferente. O cronômetro é uma abstração mais eficaz porque expõe apenas esses valores relativos, não os 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 auxiliar
fonte
2
falta cronômetro de goiabas getStartTime(), falta de apache isRunning()ahhhh
To Kra
3
@ToKra O que você faria com a hora de início? Como é tempo nano, você não pode usá-lo para nada significativo de qualquer maneira, conforme descrito nos documentos.
Trejkaz,
1
Agora você usa isso para obter os milissegundos: long stopWatch = stopWatch.elapsed (TimeUnit.MILLISECONDS);
PHPGuru
Qual versão de goiaba é? Usei 1.8 e não encontrei a classe Cronômetro
Laser Infinito
58

Agora você pode tentar algo como:

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

A saída está em ISO 8601.

Valtoni Boaventura
fonte
1
Rápido e fácil, muito obrigado! Ajuda a controlar a duração da tarefa desde o início.
ndm13
E se você alterar a hora do sistema durante o sono?
Peteter
1
@Peteter é apenas um exemplo. Se você está em uma máquina Linux, deve lidar com o relógio do hardware e o relógio gerenciado do kernel. Se você alterar o relógio do hardware, nenhum será afetado, mas no relógio gerenciado do kernel você terá problemas: Instant.now () obtém a hora do sistema e mostrará um intervalo de tempo errado.
Valtoni Boaventura
Eu nem sabia que funcionava no Android. É bom saber :)
Valtoni Boaventura 01/02/19
Não esquecendo que java.time.Instant é imutável e thread-safe :)
Amos Kosgei
38

Spring fornece uma org.springframework.util.StopWatchclasse elegante (módulo spring-core).

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

Use System.currentTimeMillis()para obter a hora de início e a hora de término e calcular a diferença.

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

Mais informações neste tutorial

user2374612
fonte
Como dito em outro lugar, currentTimeMillis () está vinculado à data / hora do sistema e não é garantido que seja monótono (por exemplo, você pode obter o tempo decorrido negativo).
oligofren
8

O código não funciona porque a variável decorrida em getElapsedTimeSecs()não é um floatou double.

Asfer
fonte
7

Não há utilitário Stopwatch embutido, mas a partir do JSR-310 (Java 8 Time) você pode fazer isso de forma simples.

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

Não fiz o benchmarking correto, mas acho que usar o cronômetro do Guava é mais eficaz.

Matsa
fonte
3

Classe de cronômetro simples e pronta 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
fonte
3

use: com.google.common.base.Stopwatch, é simples e fácil.

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

exemplo:

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

"Do something"

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

esta tarefa levou 112 moinhos

Luke_P
fonte
2

tente isso

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
fonte
1
Como dito em outro lugar, currentTimeMillis () está vinculado à data / hora do sistema e não é garantido que seja monótono (por exemplo, você pode obter o tempo decorrido negativo).
oligofren
2

Experimente isto:

/*
 * 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));
    }

}

Usar:

StopWatch sw = new StopWatch();
...
sw.startTiming();
...
String interval = sw.stopTiming();
Oke Uwechue
fonte
2
DateUtils faz parte do Apache Commons, por que não apenas usar seu StopWatch?
Bill Effin Murray
Na maioria dos casos, você usará alguma biblioteca comum como mencionado em outras respostas (Apache Commons por exemplo). Você pode até mesmo levar apenas partes da biblioteca se não precisar de tudo.
guyarad
2

Experimente isso.

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

Console:

StopWatch: 143 milliseconds.
StopWatch: 0.143 seconds.
KS
fonte
Embora isso possa ou não ser o que estava sendo perguntado na pergunta, sua resposta me ajudou com meu problema. Obrigado.
Toiletduck
currentTimeMillis()está vinculado à data / hora do sistema e não é garantido que seja monótono (por exemplo, você pode obter o tempo decorrido negativo).
oligofren
Se você decidir construir o seu próprio, use System.nanoTime()para obter sempre os resultados corretos.
oligofren
2

Performetrics oferece uma aula de cronômetro conveniente, do jeito que você precisa. Ele pode medir o tempo do relógio de parede e muito mais: ele também mede o tempo da CPU (hora do usuário e hora do sistema) se necessário. É pequeno, gratuito e você pode fazer o download no Maven Central. Mais informações e exemplos podem ser encontrados aqui: 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  |
// +-----------------+----------------------+--------------+

Você pode converter as métricas para qualquer unidade de tempo (nanossegundos, milissegundos, segundos, etc ...)

PS: Eu sou o autor da ferramenta.

Oswaldo Junior
fonte
1

Experimente isso.

Solução Java Cronômetro totalmente funcional

Aqui você obterá uma solução totalmente funcional.

Apenas um snippet da solução vinculada acima:

Você pode criar uma classe como o código abaixo e usar o método start e stop desta classe antes e depois da seção de código, você deseja medir o tempo gasto.

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

}

Obrigado.

Sukriti Sarkar
fonte
1
Embora este link possa responder à pergunta, é melhor incluir as partes essenciais da resposta aqui e fornecer o link para referência. As respostas somente com link podem se tornar inválidas se a página vinculada mudar.
AS Mackay
Obrigado @ASMackay por sua sugestão. Eu concordo completamente com você.
Sukriti Sarkar