2012-08-06 46 views
4

我是新太這個網站,所以原諒我,如果我已經發布了這個問題,在錯誤的地方或東西:)Java ScheduledThreadPoolExecutor延遲15毫秒/不一致的時間?

我一直在研究和創建測試程序不停的試圖找出什麼可能是用我創建的ScheduledThreadPoolExecutor出錯。

問題:

當運行下面的測試應用程序安排在3毫秒的固定速率運行的ScheduledThreadPoolExecutor具有大於15毫秒頻繁尖峯無序運行。它應該以每3毫秒的速率執行。

有趣的細節:

發生IDE外的問題,運行的ScheduledThreadPoolExecutor如預期的IDE如Netbeans的或內部的IntelliJ。

問:

爲什麼會收到使用定時器和的ScheduledThreadPoolExecutor類非常不一致的時間?執行之間的時間範圍爲每次執行期望的3毫秒到執行之間15毫秒的頻繁尖峯。

配置:

Java 7的更新5,IDE的IntelliJ,Windows 7中,從命令提示符下運行。

測試應用程序演示問題時,確保在IDE外部使用以查看問題。該程序將輸出大於執行期間預期時間的時間。應該是大約15毫秒,而不是預期的3.

謝謝大家的幫助! :)

package testtime; 

import javax.swing.*; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.concurrent.ScheduledThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 

public class TestTime extends JFrame { 

    public static void main(String args[]) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new TestTime().setVisible(true); 
      } 
     }); 
    } 

    JTextArea area = new JTextArea(); 
    JScrollPane pane = new JScrollPane(area); 

    ScheduledThreadPoolExecutor executor; 

    public TestTime() { 
     setSize(300, 300); 
     setAlwaysOnTop(true); 
     setLocationRelativeTo(null); 
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     area.addMouseListener(new MouseAdapter() { 
      @Override 
      public void mousePressed(MouseEvent e) { 
       area.setText("--Press anywhere to start--\n\n" + 
         "If time exceeds 3 milliseconds it will be printed here...\n\n" + 
         "------------------------------------\n\n"); 
       executor = new ScheduledThreadPoolExecutor(1); 
       executor.scheduleAtFixedRate(new Loop(), 0L, 3L, TimeUnit.MILLISECONDS); 
      } 

      @Override 
      public void mouseReleased(MouseEvent e) { 
       executor.shutdownNow(); 
      } 
     }); 

     area.setLineWrap(true); 
     area.setWrapStyleWord(true); 
     area.setText("--Press anywhere to start--"); 
     add(pane); 
    } 

    class Loop extends Thread { 
     long time = 0L; 

     @Override 
     public void run() { 
      long timeTaken = System.nanoTime() - time; 
      time = System.nanoTime(); 

      if(timeTaken > 3500000L) { 
       area.append(timeTaken+"(nanoseconds) -- "+(timeTaken/1000000L)+"(milliseconds)\n"); 
      } 
     } 
    } 
} 
+1

使用IDE(Eclipse)進行測試時,我同意在WinXP上運行的那個(唯一標記的是3-4ms) – 2012-08-06 21:58:00

+1

? – bestsss 2012-08-06 22:08:19

+0

歡迎來到SO。 +1爲一個寫得很好的問題。 – 2012-08-06 22:13:14

回答

3

我認爲你的問題來自垃圾回收器,它會定期凍結進程以從內存中刪除未使用的對象。

JVM支持幾種不同的GC algorithms。在延遲和吞吐量之間有一個折衷。

IntelliJ可能會使用低暫停GC來支持UI快速響應,而JVM默認爲IDE以外的高吞吐量。

你可以嘗試添加-Xincgc選項(選擇併發標記&掃描)到您的項目?

+0

我同意評估它可能是GC問題。 – 2012-08-07 17:41:42

+0

這是非常有希望的,但是在命令提示符下運行命令後,添加的命令似乎沒有解決問題。我一開始以爲它的確如此,但是我在IDE中不正確地測試了它,而不是在命令提示符下。 ScheduledThreadPoolExecutor在它應該是3時仍然有15毫秒的頻繁高峯。如果它不是一個很大的變化,並且在IDE中運行時沒有修復,我會忽略它,這很奇怪。謝謝你的答案:) – neptune692 2012-08-07 19:21:24

+0

另一個說明我沒有嘗試將命令添加到IDE,因爲由於某種原因,問題**不會發生在IDE內部我在命令提示符下嘗試了它'java -Xincgc -jar SpeedTest.jar「並獲得了相同的結果。如果我在運行編譯桌面版本時從IDE運行,則需要更奇怪的問題是從命令提示符處運行修復。因此,如果IDE中的應用程序同時運行,問題就會消失在從命令提示符運行的桌面版本中。15毫秒尖峯消失......我甚至不知道從哪裏開始。 – neptune692 2012-08-07 19:30:53

1

我認爲Windows計時器根本沒有這麼好的分辨率。如果您在Google上找到更多關於該主題的信息,您可以使用Google http://www.google.de/search?q=windows+timer+resolution

+1

我會+1,但我記得一個同事做測試,顯示Windows中的低分辨率計時器問題已在Win7和可能的Vista中修復。 – 2012-08-07 17:40:53

1

從技術上講,Timer和ScheduledExecutor接口指定的合約不保證任務將按指定的時間間隔執行。他們只是保證不會比間隔更早運行它們。