简体   繁体   English

如何测量经过的时间

[英]How to measure elapsed time

I have a 10 and 20 question game.我有一个 10 和 20 个问题的游戏。 I need to count how much time is passed when a user finishes the game.我需要计算用户完成游戏时过去了多少时间。

Timer T=new Timer();
T.scheduleAtFixedRate(new TimerTask() {         
    @Override
    public void run() {
        runOnUiThread(new Runnable()
        {                
            public void run()
            {
                countdown.setText(""+count);
                count++;                
            }
        });
    }
}, 1000, 1000);

I use this to stop the counter:我用它来停止计数器:

T.cancel();

Now I need two things:现在我需要两件事:

  • A way how to count the elapsed time and store it in a variable一种如何计算经过时间并将其存储在变量中的方法
  • I need the final value to be a double, for example final score is: 15.49 seconds.我需要将最终值设为双精度值,例如最终得分为:15.49 秒。

When the game starts:游戏开始时:

long tStart = System.currentTimeMillis();

When the game ends:游戏结束时:

long tEnd = System.currentTimeMillis();
long tDelta = tEnd - tStart;
double elapsedSeconds = tDelta / 1000.0;

Per the Android docs SystemClock.elapsedRealtime() is the recommend basis for general purpose interval timing.根据 Android 文档SystemClock.elapsedRealtime()是通用间隔计时的推荐基础。 This is because, per the documentation, elapsedRealtime() is guaranteed to be monotonic, [...], so is the recommend basis for general purpose interval timing.这是因为,根据文档,elapsedRealtime() is guaranteed to be monotonic, [...], so is the recommend basis for general purpose interval timing.

The SystemClock documentation has a nice overview of the various time methods and the applicable use cases for them. SystemClock 文档很好地概述了各种时间方法及其适用的用例。

  • SystemClock.elapsedRealtime() and SystemClock.elapsedRealtimeNanos() are the best bet for calculating general purpose elapsed time. SystemClock.elapsedRealtime()SystemClock.elapsedRealtimeNanos()是计算通用经过时间的最佳选择。
  • SystemClock.uptimeMillis() and System.nanoTime() are another possibility, but unlike the recommended methods, they don't include time in deep sleep. SystemClock.uptimeMillis()System.nanoTime()是另一种可能性,但与推荐的方法不同,它们不包括深度睡眠时间。 If this is your desired behavior then they are fine to use.如果这是您想要的行为,那么它们可以很好地使用。 Otherwise stick with elapsedRealtime() .否则坚持使用elapsedRealtime()
  • Stay away from System.currentTimeMillis() as this will return "wall" clock time.远离System.currentTimeMillis()因为这将返回“墙上”时钟时间。 Which is unsuitable for calculating elapsed time as the wall clock time may jump forward or backwards.这不适合计算经过时间,因为挂钟时间可能会向前或向后跳跃。 Many things like NTP clients can cause wall clock time to jump and skew.许多诸如 NTP 客户端之类的东西会导致挂钟时间跳跃和倾斜。 This will cause elapsed time calculations based on currentTimeMillis() to not always be accurate.这将导致基于currentTimeMillis()经过时间计算并不总是准确的。

When the game starts:游戏开始时:

long startTime = SystemClock.elapsedRealtime();

When the game ends:游戏结束时:

long endTime = SystemClock.elapsedRealtime();
long elapsedMilliSeconds = endTime - startTime;
double elapsedSeconds = elapsedMilliSeconds / 1000.0;

Also, Timer() is a best effort timer and will not always be accurate.此外, Timer() 是一个尽力而为的计时器,并不总是准确的。 So there will be an accumulation of timing errors over the duration of the game.因此,在游戏过程中会累积计时错误。 To more accurately display interim time, use periodic checks to System.currentTimeMillis() as the basis of the time sent to setText(...) .要更准确地显示中间时间,请使用定期检查System.currentTimeMillis()作为发送到setText(...)的时间的基础。

Also, instead of using Timer , you might want to look into using TimerTask , this class is designed for what you want to do.此外,您可能想考虑使用TimerTask而不是使用Timer ,这个类是为您想要做的事情而设计的。 The only problem is that it counts down instead of up, but that can be solved with simple subtraction.唯一的问题是它是倒数而不是倒数,但这可以通过简单的减法来解决。

Even better!甚至更好!

long tStart = System.nanoTime();
long tEnd = System.nanoTime();
long tRes = tEnd - tStart; // time in nanoseconds

Read the documentation about nanoTime()!阅读有关 nanoTime() 的文档

There are many ways to achieve this, but the most important consideration to measure elapsed time is to use System.nanoTime() and TimeUnit.NANOSECONDS as the time unit.有很多方法可以实现这一点,但测量经过时间的最重要的考虑因素是使用System.nanoTime()TimeUnit.NANOSECONDS作为时间单位。 Why should I do this?我为什么要这样做? Well, it is because System.nanoTime() method returns a high-resolution time source, in nanoseconds since some reference point (ie Java Virtual Machine's start up).嗯,这是因为System.nanoTime()方法返回一个高分辨率的时间源,从某个参考点(即 Java 虚拟机的启动)起以纳秒为单位。

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time.此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。

For the same reason, it is recommended to avoid the use of the System.currentTimeMillis() method for measuring elapsed time.出于同样的原因,建议避免使用System.currentTimeMillis()方法来测量经过的时间。 This method returns the wall-clock time, which may change based on many factors.此方法返回wall-clock时间,该时间可能会因多种因素而变化。 This will be negative for your measurements.这将对您的测量产生负面影响。

Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger.请注意,虽然返回值的时间单位是毫秒,但该值的粒度取决于底层操作系统,可能会更大。 For example, many operating systems measure time in units of tens of milliseconds.例如,许多操作系统以几十毫秒为单位测量时间。

So here you have one solution based on the System.nanoTime() method, another one using Guava , and the final one Apache Commons Lang所以这里你有一个基于System.nanoTime()方法的解决方案,另一个使用Guava ,最后一个Apache Commons Lang

public class TimeBenchUtil
{
    public static void main(String[] args) throws InterruptedException
    {
        stopWatch();
        stopWatchGuava();
        stopWatchApacheCommons();
    }

    public static void stopWatch() throws InterruptedException
    {
        long endTime, timeElapsed, startTime = System.nanoTime();

        /* ... the code being measured starts ... */

        // sleep for 5 seconds
        TimeUnit.SECONDS.sleep(5);

        /* ... the code being measured ends ... */

        endTime = System.nanoTime();

        // get difference of two nanoTime values
        timeElapsed = endTime - startTime;

        System.out.println("Execution time in nanoseconds   : " + timeElapsed);
    }

    public static void stopWatchGuava() throws InterruptedException
    {
        // Creates and starts a new stopwatch
        Stopwatch stopwatch = Stopwatch.createStarted();

        /* ... the code being measured starts ... */

        // sleep for 5 seconds
        TimeUnit.SECONDS.sleep(5);
        /* ... the code being measured ends ... */

        stopwatch.stop(); // optional

        // get elapsed time, expressed in milliseconds
        long timeElapsed = stopwatch.elapsed(TimeUnit.NANOSECONDS);

        System.out.println("Execution time in nanoseconds   : " + timeElapsed);
    }

    public static void stopWatchApacheCommons() throws InterruptedException
    {
        StopWatch stopwatch = new StopWatch();
        stopwatch.start();

        /* ... the code being measured starts ... */

        // sleep for 5 seconds
        TimeUnit.SECONDS.sleep(5);

        /* ... the code being measured ends ... */

        stopwatch.stop();    // Optional

        long timeElapsed = stopwatch.getNanoTime();

        System.out.println("Execution time in nanoseconds   : " + timeElapsed);
    }
}

From Java 8 onward you can try the following:从 Java 8 开始,您可以尝试以下操作:

import java.time.*;
import java.time.temporal.ChronoUnit;

Instant start_time = Instant.now();
// Your code
Instant stop_time = Instant.now();

System.out.println(Duration.between(start_time, stop_time).toMillis());

//or

System.out.println(ChronoUnit.MILLIS.between(start_time, stop_time));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM