2011-02-01 50 views
2

回覆:要求在事件分派線程上創建Swing對象。在Java程序中使用多個線程vs vs需要在EDT上創建Swing對象

我正在研究一個應用程序,其目的是監視和顯示各種遠程嵌入式服務器的狀況。我對Java非常陌生,並且我對Swing Objects和EDT的要求的理解並不完整。

主GUI開始對EDT以通常的方式如下,

javax.swing.SwingUtilities.invokeLater(new Runnable() { 

     public void run() { 
      createAndShowGUI(); 
     } 
    }); 

然後,用戶可以選擇對應於所述遠程機器的一個或另一個的一個或多個菜單選項。這樣做的效果是創建一個新的線程,每次如下

   new Thread(new VoterStatus(itemNumber)).start(); 

它調用VoterStatus的類「跑」的方法這反過來又創造了JFrame的一個新窗口。新線程(VoterStatus類的一個實例)然後詢問(TCP等)指定的特定遠程(itemNumber),收集各種信息並將其顯示在JFrame中。

可能有任何數量的這樣的線程對應於VoterStatus的一個實例,它們都會更新它們自己的窗口。這些不同的窗口/ JFrame /任務之間沒有數據共享。

這似乎工作得很好,但是安全嗎?

我違反了在EDT上創建Swing組件的規則嗎?

使用SwingWorker類會有好處嗎?

我希望Java程序員在這些問題上有更多經驗的評論。

感謝 史蒂夫

+0

您是否僅使用EDT來啓動主GUI?如果是,那麼一切都很好。但是,如果在EDT中創建了後續窗口,並且它們的創建時間足夠長(即> 200 ms),則GUI將凍結以便創建新窗口。 – Rogach 2011-02-01 04:30:28

+0

嗨Rogach - 這個評論似乎與其他一些答案略有不同,儘管如果確實如此,我更喜歡它。我正在創建EDT上的主GUI,但其他窗口是在EDT中啓動的線程上啓動的。任何更多的想法。感謝史蒂夫 – Steve 2011-02-02 04:59:10

回答

5

從標題爲The Event Dispatch Thread

一些Swing組件方法Swing指南一節中的API規範標有「線程安全的」;這些可以從任何線程安全地調用。必須從事件派發線程調用所有其他Swing組件方法。忽略此規則的程序可能在大多數情況下都能正常運行,但會遇到難以重現的不可預知的錯誤。

我總是在EDT上調用我的方法,所以我不浪費時間追逐gremlins。

編輯:

我剛纔讀另一張貼其中指出註釋「線程安全」已經從JDK7 API中的許多方法去除。 http://forums.oracle.com/forums/thread.jspa?threadID=2167051。這看起來是確保所有影響GUI的方法都在EDT上執行的另一個原因。

0

您可能很安全,但您可以確定在EDT中創建其他UI組件,就像您爲主應用程序一樣。

但是,我會建議一種不同的方法。而不是發射一個新的Thread,它爲每個新的VoterStatus創建窗口和東西,在菜單或任何其他地方響應ActionEvents在EDT中創建用戶界面組件,並且僅在不同的線程中處理網絡材料。然後獲得結果並使用EDT顯示它們。正如你所建議的,一個SwingWorker是理想的 - 這正是它的設計目的。這對我來說代表了一種更清晰的分離,儘可能地將UI內容與網絡內容分開。

2

@camickr有權利。同步錯誤的程序可能會出現工作大多數的時間,但結果不可靠。討論了幾種相關的方法hereSwingWorkerFuture接口的特別方便的實現,因爲process()在事件分派線程上運行。

0

我並沒有真正回答我自己的問題,但我很想感謝那些回答並提出後續問題的人。

Rogash評論說,如果我只是在EDT上創建GUI,我會沒事的,但是這看起來不符合嚴格的規則解釋?

EDT中創建了額外的線程,但它們仍然是單獨的線程。

儘管GUI和通信的分離可能會更好,但我認爲這會增加主要GUI代碼的複雜度,因爲它必須確定哪個窗口來自各種事件,然後更新正確的窗口,而不是提到各種線程和主GUI線程之間的通信。也許我誇大了這個難題(我還沒有設計或想過如何編碼它),但它似乎更復雜。每個線程/ JFrame已經有幾個JToggleButton數組(30個元素)引起潛在的事件,10個左右的JTextField數組具有相同數量的元素需要更新。

當然,如果我的方法不安全,我將不得不改變它,就是這樣!

實際上,我不知道我是否可以更好地保持它們的狀態,並使用互斥鎖或信號量來確保一次只有一個線程正在訪問Swing方法。實際上沒有長時間的用戶操作或任何其他活動需要很長時間,只有大量的TCP或UDP數據包被接收到,需要更新屏幕顯示。

再次感謝 史蒂夫

PS我試圖在這個論壇註冊,但我覺得這個討論將留在我的未註冊的人物。