2011-12-07 52 views
9

使用Java預定執行程序時遇到的一個特點是,想知道我所經歷的是否正常。Java預定執行程序的準確性

我需要安排以5秒預定義速度執行的任務。預計這些任務的執行時間不會超過5秒,但是當它們運行的​​時間低於5秒時,備份的任務列表應該快速連續運行以趕上。在運行任務時,瞭解原始預定執行時間是什麼很重要(請考慮scheduledExecutionTime()java.util.TimerTask)。最後,我需要跟蹤計劃時間和實際時間之間的差異,以確定計劃何時「漂移」以及計劃多少時間。

到目前爲止,我已經通過使用Java執行人實現這一切,和下面的類說明了總體思路:

public class ExecutorTest { 
    public static final long PERIOD = 5000; 

    public static void main(String[] args) { 
     Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(
       new Command(), 0, PERIOD, TimeUnit.MILLISECONDS); 
    } 

    private static final class Command implements Runnable { 
     long timestamp = 0; 

     public void run() { 
      long now = System.currentTimeMillis(); 

      if (timestamp == 0) { 
       timestamp = now; 
      } 

      // Drift is the difference between scheduled time and execution time 
      long drift = now - timestamp; 

      String format = "Ran at %1$tF %<tT,%<tL; drift: %2$dms"; 
      System.out.println(String.format(format, now, drift)); 

      timestamp += PERIOD; 
     } 
    } 
} 

運行上述代碼顯示漂移(在理想情況下應儘量靠近0)可能會波動多達幾秒鐘,其結果是執行任務過早或過遲。我創建了一個圖表運行此爲約150分鐘的結果:

Java executor drift

所以我的第一個問題是,這是否是正常的。我的環境由32位Windows XP和Java 1.5更新21組成(儘管Java 6 update 22產生了類似的結果)。

第二個問題是是否有簡單的方法來減少漂移量。如果我使用簡單的java.util.Timer或甚至僅使用Thread.sleep(),則漂移不存在。

最後,在使用預定的執行程序時,是否有更好的方法來跟蹤預定的執行時間?

回答

8

預定的執行程序服務使用System.nanoTime,它不會像currentTimeMillis那樣漂移。除非您在具有多個CPU插槽的XP系統上運行。在XP中,操作系統調用System.nanoTime()使用的錯誤在套接字之間不一致,因此線程會切換其運行的套接字,因此您可以期望看到這種跳轉。 (在Vista/7上這不是問題)

在帶有一個套接字的Linux系統上,您的程序報告0 - 3 ms漂移。

試試看這個程序。

public static void main(String... args) throws Exception { 
    long start = System.nanoTime(); 
    long time = start; 
    while(time < start + 3e10) { 
     long now = System.nanoTime(); 
     if (now < time || now > time + 50000) { 
      System.out.println(now - time); 
      now = System.nanoTime(); 
     } 
     time = now; 
    } 
} 

在i7系統上,我看到大約10個跳躍達2毫秒。如果我使用機器,我會看到更多。我期望你可能會看到的是巨大的消極和積極的時機。

0

對我來說看起來很正常,它在5000/2的範圍內變化。代替格式+ println,您應該嘗試快速記錄,因此println的開銷漂移不會被測量。會很有趣。