2011-08-25 30 views
4

我有下面的示例代碼中的問題,顯示了EventQueue中不一致的行爲:的EventQueue不一致的ID

public static void main(String[] args) throws InvocationTargetException, InterruptedException { 

    final long[] id1 = new long[ 1 ]; 
    final long[] id2 = new long[ 1 ]; 

    EventQueue.invokeAndWait(new Runnable() { 
     @Override public void run() { 
     id1[ 0 ] = Thread.currentThread().getId(); 
     } 
    }); 

    Thread.sleep(5000); 

    EventQueue.invokeAndWait(new Runnable() { 
     @Override public void run() { 
     id2[ 0 ] = Thread.currentThread().getId(); 
     } 
    }); 

    System.out.println("id1 = " + id1[0]); 
    System.out.println("id2 = " + id2[0]); 

    if(id1[0]!=id2[0]){ 
     System.out.println("These ID's don't match, even though they were retrieved from the same thread."); 
    } 

    } 

基本上,它得到的EventQueue線程ID,等待5秒鐘,然後再獲取ID 。

由於某些原因,ID不匹配。顯然,EventQueue被銷燬並重新創建。這是正常的行爲嗎?這是記錄在某處嗎?這是一個錯誤嗎?即使它是一個不同的實例,它不應該有相同的ID嗎?如果我不執行Thread.sleep,則ID將匹配。

我的另一個問題是:我該如何解決這個問題?我正在使用只能在創建線程上訪問的對象。如果這恰好是eventqueue(它不一定非要),我必須能夠檢查它是否仍然是eventqueue。

回答

2

AWT事件調度線程可能會在不再需要時關閉this page描述了JDK 7中實際實現的規範和行爲)。

這似乎發生在這裏:您使用系統EventQueue來處理一個事件。那麼沒有什麼需要它了(沒有AWT/Swing組件,...)。過了一段時間後,它關閉了。

然後,當您再次使用EventQueue時,另一個線程開始接管該角色。

所以這裏所發生的是,你的Runnable.run()方法得到的兩個不同的線程執行這兩個線程都是「AWT事件派發線程」,只是在JVMs生命週期的不同時間。

也許使用EventQueue.isDispatchThread()這個特殊的套管將是一個可能的解決方案。

+0

謝謝。我希望有一個比EventQueue線程本身的特殊檢查更好的方法,但我想如果必須我必須。 :) – Tovi7

+0

嗯,我想說這是你的需求中的特殊情況,因爲你想把兩個不同的事件線程看作是相同的。如果你真的**只想讓同一個線程訪問某個東西,那麼只需要檢查線程ID就足夠了。 –