我的程序中有3個主類。第一個擴展applet(作爲我的主要),第二個是一個線程(實現Runnable),用於處理後端物流/與服務器的通信,第三個是JPanel類,它創建GUI(這是創建的在主線程(小程序)中調用SwingUtilities.invokeAndWait()
的新線程如何使用wait()和notifyAll()在GUI類和邏輯線程之間進行通信
GUI類與後端線程多次通信以獲取數據以顯示在屏幕上我的問題是GUI在後端類提供數據之前顯示它的組件,所以我想告訴GUI在另一個線程中調用一個方法,等待它回聲,然後顯示它的組件。變體:
Object[] data = backend.Method1();
wait();
showComponents(data);
在GUI類中,並將notifyAll();
置於後端線程中Method1的底部,但我在netbeans中發出警告(在同步上下文之外調用Object.wait),並在程序崩潰時遇到java.lang.illegalmonitorstateexception
運行。我已經嘗試將關鍵字添加到這兩種方法,但這會導致程序凍結。
我(很明顯,我敢肯定)只是在學習多線程:我在這裏誤解了什麼?
我有一種感覺,認爲它的JPanel類沒有實現runnable。
編輯:根據@ MadProgrammer的建議,我正在使用一個SwingWorker,它似乎在做伎倆。謝謝你指點我,我從來沒有聽說過他們。
final JLabel loading = new JLabel("loading");
loading.setVisible(true);
add(loading);
SwingWorker sw = new SwingWorker<Map<String, ArrayList<Time[]>>, Void>() {
@Override
public Map<String, ArrayList<Time[]>> doInBackground(){
System.out.println("doing");
Map<String, ArrayList<Time[]>> toReturn = dbh.getTimes(specToPass);
return toReturn;
}
public void done(){
try {
loading.setVisible(false);
Map<String, ArrayList<Time[]>> weekMap = new HashMap(this.get());
showTimes(weekMap);
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
}
};
sw.execute();
我希望你能讓我知道如果我沒有正確實施這個。再次感謝。
如果我打破了GUI的方法分爲兩個最新進展 - 一個調用在後臺線程的方法,並顯示加載窗口。然後,在後臺線程的方法底部,讓它在GUI線程上調用第二個方法,它隱藏加載窗口並顯示組件?這看起來好像會起作用,但我恐怕它有點難看? – drewmoore 2013-03-19 05:55:39
哇!您在短短5分鐘內閱讀/理解這7個網頁? Legend .. – 2013-03-19 05:58:35
你的用戶界面應該調用後臺線程來獲取數據,並將其引用到類似於具有'loadingDone'和'loadingFailed'等方法的接口。然後你應該在用戶界面上顯示「等待」消息,也許使用一個漂亮的動畫GIF或其他東西。當調用'loadingDone'(或'Failed')時。你必須將呼叫重新同步到EDT(使用'SwingUtilities.invokeLater',然後將數據推送到用戶界面。就我個人而言,我會通過'loadingData'方法傳回數據 – MadProgrammer 2013-03-19 05:59:00