2015-11-14 81 views
1

我正在做模擬項目,其中有數百個CPU綁定作業運行10到50毫秒。作業是一個Runnable對象,具有指定的運行時間,作業將使CPU保持忙碌狀態。線程池中有10個線程正在等待工作到達。我將請求速率設置爲每秒40個請求,並將所有作業運行時間設置爲10ms。但結果非常糟糕。所有作業運行至少15ms。沒有工作運行10毫秒。我用15ms的工作測試了實驗,並得到了正確的結果。爲什麼10ms作業至少運行15ms?(我正在使用WINDOWS8)。爲什麼小於15ms的忙等待不一致?

public class CpuBoundJob implements Runnable { 
long runningTime 
    public CpuBoundJob(long runningTime) { 
     this.runningTime=runningTime; 
      } 
    @Override 
    public void run() { 

     long timeToWait = this.runningTime; 
     long startTime = System.currentTimeMillis(); 
     while(startTime + timeToWait > System.currentTimeMillis()); 
} 
} 
+1

您的系統計時器的分辨率可能是15ms。你可以嘗試['System.nanoTime()'](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#nanoTime--),但它可能沒有更多分辨率。鏈接的Javadoc說(部分)*除了分辨率至少和currentTimeMillis()一樣好,沒有任何保證。* –

回答

1

在許多系統(特別是視窗,IIRC),System.currentTimeMillis()由時鐘只精確到15毫秒左右的支持。

但是,它更糟糕:System.currentTimeMillis()措施時間自從Unix時代由系統時鐘測量。因此,如果您更改計算機上的時間(例如,由於將系統時鐘同步到時間源或閏秒或其他任何事項),則currentTimeMillis()可以隨意向前或向後跳轉大量時間。

如果你想測量經過時間,NEVER使用currentTimeMillis()。改爲使用System.nanoTime()。作爲獎勵,在大多數系統上,它的調用也相當便宜,並且更精確。

+0

我已經使用System.nanoTime(),它比System.currentTimeMillis )。使用System.nanoTime()時,有些作業甚至運行0ms。 –

+0

@MuhammadAbdullah當納秒時間也有15ms的結果時,那麼從那個時鐘源的某個時刻從0跳到15會發生。如果你不走運,那就是錄製startTime和檢查循環之間的那一刻。有效地等待0時間,但你無能爲力。當你測試'nanoTime'時,你確定把你的等待時間乘以1000000? – zapl

+0

@MuhammadAbdullah:在Windows 8上,'nanoTime()'應該有更好的分辨率。你可以在不是這種情況下顯示代碼嗎? –