[英]How to measure elapsed time
我有一個 10 和 20 個問題的游戲。 我需要計算用戶完成游戲時過去了多少時間。
Timer T=new Timer();
T.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable()
{
public void run()
{
countdown.setText(""+count);
count++;
}
});
}
}, 1000, 1000);
我用它來停止計數器:
T.cancel();
現在我需要兩件事:
游戲開始時:
long tStart = System.currentTimeMillis();
游戲結束時:
long tEnd = System.currentTimeMillis();
long tDelta = tEnd - tStart;
double elapsedSeconds = tDelta / 1000.0;
根據 Android 文檔SystemClock.elapsedRealtime()
是通用間隔計時的推薦基礎。 這是因為,根據文檔,elapsedRealtime() is guaranteed to be monotonic, [...], so is the recommend basis for general purpose interval timing.
SystemClock 文檔很好地概述了各種時間方法及其適用的用例。
SystemClock.elapsedRealtime()
和SystemClock.elapsedRealtimeNanos()
是計算通用經過時間的最佳選擇。SystemClock.uptimeMillis()
和System.nanoTime()
是另一種可能性,但與推薦的方法不同,它們不包括深度睡眠時間。 如果這是您想要的行為,那么它們可以很好地使用。 否則堅持使用elapsedRealtime()
。System.currentTimeMillis()
因為這將返回“牆上”時鍾時間。 這不適合計算經過時間,因為掛鍾時間可能會向前或向后跳躍。 許多諸如 NTP 客戶端之類的東西會導致掛鍾時間跳躍和傾斜。 這將導致基於currentTimeMillis()
經過時間計算並不總是准確的。游戲開始時:
long startTime = SystemClock.elapsedRealtime();
游戲結束時:
long endTime = SystemClock.elapsedRealtime();
long elapsedMilliSeconds = endTime - startTime;
double elapsedSeconds = elapsedMilliSeconds / 1000.0;
此外, Timer() 是一個盡力而為的計時器,並不總是准確的。 因此,在游戲過程中會累積計時錯誤。 要更准確地顯示中間時間,請使用定期檢查System.currentTimeMillis()
作為發送到setText(...)
的時間的基礎。
此外,您可能想考慮使用TimerTask
而不是使用Timer
,這個類是為您想要做的事情而設計的。 唯一的問題是它是倒數而不是倒數,但這可以通過簡單的減法來解決。
甚至更好!
long tStart = System.nanoTime();
long tEnd = System.nanoTime();
long tRes = tEnd - tStart; // time in nanoseconds
閱讀有關 nanoTime() 的文檔!
有很多方法可以實現這一點,但測量經過時間的最重要的考慮因素是使用System.nanoTime()
和TimeUnit.NANOSECONDS
作為時間單位。 我為什么要這樣做? 嗯,這是因為System.nanoTime()
方法返回一個高分辨率的時間源,從某個參考點(即 Java 虛擬機的啟動)起以納秒為單位。
此方法只能用於測量經過的時間,與系統或掛鍾時間的任何其他概念無關。
出於同樣的原因,建議避免使用System.currentTimeMillis()
方法來測量經過的時間。 此方法返回wall-clock
時間,該時間可能會因多種因素而變化。 這將對您的測量產生負面影響。
請注意,雖然返回值的時間單位是毫秒,但該值的粒度取決於底層操作系統,可能會更大。 例如,許多操作系統以幾十毫秒為單位測量時間。
所以這里你有一個基於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);
}
}
從 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.