2013-12-13 92 views
0

我有一個線程可以接收來自ArrayBlockingQueue() connectionPool.的對象如果ArrayBlockingQueue()爲空,線程可能會被阻塞。爲了測量該調用線程被阻塞的時候,我用下面的代碼:Linux上的Java:使用System.nanotime()測量線程的流逝時間

long start = System.nanoTime(); 
DataBaseEndPoint dbep = connectionPool.take(); 
long end = System.nanoTime(); 
long elapsed = (end - start)/1000000; 

現在,我關心的是,暢通線程可能會開始在多處理器機器不同的處理器上運行。在這種情況下,我不完全確定在不同處理器上使用的「系統定時器」是否相同。 這篇博文(http://www.javacodegeeks.com/2012/02/what-is-behind-systemnanotime.html)表明,Linux爲每個處理器(也用於System.nanotime())使用不同的時間戳記計數器,這可能會在上面的示例中真正地混淆了經過時間的計算。

使用CLOCK_MONOTONIC標誌從clock_gettime讀取該值,其中 使用TSC或HPET。與Windows的唯一區別在於,Linux甚至不嘗試同步從不同CPU讀取的TSC值, 它只是將它原樣返回。這意味着值可以跳回來,並且在CPU讀取它的位置依賴於CPU。

但是,該鏈接(http://lwn.net/Articles/209101/)表明TSC不再用於高分辨率定時器。

...最近更新的高分辨率定時器和動態滴答補丁 集包括禁用TSC的更改。看來, 高分辨率定時器和動態剔特徵與 的TSC不兼容...

所以,問題是,什麼是使用一臺Linux機器價值迴歸System.nanotime()目前?並且,使用System.nanotime()可安全地測量上述情況下的經過時間(阻塞的線程在另一個處理器上啓動)。如果不安全,還有什麼選擇?

回答

0

有關虛擬機(以及一般生活)非常寶貴的一件事是抽象。線程的執行時間不會因內核數量而有所不同;不是在Linux中,也不在Windows中......我希望我不會誤解你的問題。

(雖然我使用的currentTimeMillis(),nanotime是在不同的尺度相同,當然)

檢查下列例子我製作:

public class SynchThreads { 

    public static void main(String[] args) throws InterruptedException { 
     GreedyTask gtA = new GreedyTask("A"); 
     GreedyTask gtB = new GreedyTask("B"); 
     Thread a = new Thread(gtA); 
     Thread b = new Thread(gtB); 
     a.start(); 
     b.start(); 
     a.join(); 
     b.join(); 
     System.out.println(gtA.toString()+" running time: "+gtA.getRunningTime()); 
     System.out.println(gtB.toString()+" running time: "+gtB.getRunningTime()); 
    } 

    private static class GreedyTask implements Runnable { 

     private long startedTime, finishedTime, totalRunTime; 
     private String myName; 

     public GreedyTask(String pstrName) { 
      myName = pstrName; 
     } 

     public void run() { 
      try { 
       startedTime = System.currentTimeMillis(); 
       randomPowerNap(this); 
       finishedTime = System.currentTimeMillis(); 
       totalRunTime = finishedTime - startedTime; 
      } catch (Exception e) { System.err.println(e.getMessage()); } 
     } 

     public String toString() { return ("Task: " + myName); } 
     public long getRunningTime() { return this.totalRunTime; } 
    } 

    private static synchronized void randomPowerNap(GreedyTask gt) throws  InterruptedException { 
     System.out.println("Executing: "+gt.toString()); 
     long random = Math.round(Math.random()*15000); 
     System.out.println("Random time for "+gt+" is: "+random); 
     Thread.sleep(random); 
    } 
} 

下面是一個輸出在4個內核的Windows機器運行:

Executing: Task: A 
Random time for Task: A is: 1225 
Executing: Task: B 
Random time for Task: B is: 4383 
Task: A running time: 1226 
Task: B running time: 5609 // what's funny about this? this is equal to Btime - Atime 

這是在一個4個核的Linux機器上運行

Executing: Task: A 
Random time for Task: A is: 13577 
Executing: Task: B 
Random time for Task: B is: 5340 
Task: A running time: 13579 
Task: B running time: 18920 // same results 

結論:B總時間增加了必須等待的時間,而randomPowerNap被A阻止,因此由於虛擬機的硬件抽象,線程看到它們的運行時間沒有差異,因爲它們都運行在' VIRTUAL BIG CORE',如果你知道我的意思。

我希望這有助於。