2012-02-22 58 views
4

在我的帶有Swing GUI的Java應用程序中,我想要實現以下功能。Java Swing應用程序:如何從GUI線程獲取數據到另一個線程?

有一個非GUI線程正在運行,執行一些工作。有一點,這個線程需要用戶輸入才能繼續。然後,我想對GUI進行一些更改,等待特定的GUI操作(如用戶按下OK按鈕),從GUI獲取輸入數據到非GUI線程,並讓它繼續計算。

環顧四周,我發現了很多關於如何從另一個線程上的Swing GUI線程啓動執行(長時間運行)任務的信息,但沒有解決我的問題。

SwingUtilites.invokeAndWait聽起來像它的工作,但首先,它需要一個Runnable參數,而不是一個Callable的,所以返回的結果沒有直接的方式,第二,它沒有解決的等待一定的問題GUI事件。

我意識到我可以用自己的解決方案來彌補自己的解決方案。一個CountDownLatch,但對我來說,這個問題似乎足夠頻繁,因爲有一個標準的解決方案。

所以,我的問題是:這是一個真正常見的問題,如果是的話,是否有標準庫/庫中的解決方案?如果沒有標準的解決方案,你會如何解決它?如果這個問題不經常發生,爲什麼不呢?

+0

查看類似的問題http:// stackoverflow。com/questions/3981924/how-to-retrieve-a-value-that-must-be-calculated-on-another-thread – 2014-02-19 01:49:51

回答

6

啓動GUI更改非常簡單,所以我假設你只是詢問有關將數據返回給工作線程的問題。

首先,創建一個Blocking Queue。讓工作者線程在隊列上調用take(),並將其阻塞。在GUI空間中,一旦用戶輸入有效的輸入,將其放入隊列offer(),工作線程將接收數據並可以繼續。

+0

好主意,謝謝。 – sandris 2012-02-22 16:16:53

+1

+1用於使用更高級別的抽象,而不是顯式鎖定。如果你用這種方式處理多線程,它就是*方式方式*更容易獲得正確的代碼(沒有細微的錯誤)。 – 2012-02-22 18:24:16

1

我認爲,你可以使用的ExecutorService,你也可以通過未來界面跟蹤任務的進度。

+0

我沒有任務來跟蹤進度。我想等待用戶輸入。 – sandris 2012-02-22 16:01:17

0
final bool result = doSomething(); 
SwingUtilities.invokeLater(new Runnable(){ 
     //Runnable method implementation. 
     //use result in your method like local var. 
    }); 

請確保您的共享數據是同步的使用鎖定對象。 如果您需要將參數傳遞給Runnable,只需將您的局部變量設置爲最終, 並在run方法中使用它們。

+0

我不想將參數傳遞給'Runnable',我想從那裏得到結果。我知道可以通過改變線程安全對象來實現這一點,但從方法獲取返回值會更清晰。 – sandris 2012-02-22 16:09:43

+0

然後,只需創建一個類成員並在可運行對象中對其進行更改即可。唯一需要的是同步這個對象。 – AlexTheo 2012-02-22 19:19:07

1

java.awt.EventQueue.invokeLater很適合在AWT EDT上運行代碼。可能最好是複製可變數據或更好地使用不可變數據。鎖可能,但有點冒險。

如果你的其他線程是一個事件調度循環,你可以爲你的線程實現類似invokeLater(但不要使它成爲靜態!)。可能在一些對線程行爲有意義的接口後面使用它 - 所以它是真實的操作而不是run,它被指定爲做任何它喜歡的事情。如果你的線程要阻塞,那麼BlockQueue是好的,但不要阻止來自AWT EDT。

java.awt.EventQueue.invokeAndWait就像使用鎖。可能你會使用另一個鎖。或者也可以像你自己的線索那樣鎖定invokeAndWait。如果你不這樣做,無論如何AWT都會使用鎖。所以,不受控制的嵌套鎖定,可能意味着死鎖。請勿使用invokeAndWait

+0

那麼你基本上說沒有現成的解決方案,並且將'SwingUtilities.invokeLater'與我自己的鎖結合使用是唯一的方法嗎? – sandris 2012-02-22 16:06:59