介紹Swing線程相關(guān)處理
我們知道這將在非Swing線程中調(diào)用,因?yàn)樵撌录侵苯釉贚ookupManager中觸發(fā)的,這將不是在Swing線程中執(zhí)行。因?yàn)樗械拇a功能上都是異步的(我們不必等待監(jiān)聽器方法允許結(jié)束后才調(diào)用其它代碼),我們可以通過SwingUtilities.invokeLater()將這些代碼改道到Swing線程。下面是新的方法,傳入一個(gè)匿名Runnable到SwingUtilities.invokeLater():
- public void lookupCompleted(final LookupEvent e) {
- //notice the threading
- SwingUtilities.invokeLater( new Runnable() {
- public void run() {
- outputTA.setText("");
- String[] results = e.getResults();
- for (int i = 0; i < results.length; i++) {
- String result = results[i];
- outputTA.setText(outputTA.getText() + " " + result);
- }
- }
- }
- );
- }
如果任何LookupListener不是在Swing線程中執(zhí)行,我們可以在調(diào)用線程中執(zhí)行監(jiān)聽器代碼。作為一個(gè)原則,我們希望所有的監(jiān)聽器都迅速地接到通知。所以,如果你有一個(gè)監(jiān)聽器需要很多時(shí)間來處理自己的功能,你應(yīng)該創(chuàng)建一個(gè)新的線程或者把耗時(shí)代碼放入ThreadPool中等待執(zhí)行。
最后的步驟是讓LookupManager在非Swing線程中執(zhí)行l(wèi)ookup。當(dāng)前,LookupManager是在JButton的 ActionListener的Swing線程中被調(diào)用的?,F(xiàn)在是我們做出決定的時(shí)候,或者我們?cè)贘Button的ActionListener中引入一個(gè)新的線程,或者我們可以保證lookup自己在非Swing線程中執(zhí)行,自己開始一個(gè)新的線程。我選擇盡可能和Swing類貼近地管理Swing線程。這有助于把所有Swing邏輯封裝在一起。如果我們把Swing線程邏輯添加到LookupManager,我們將引入了一層不必要的依賴。并且,對(duì)于 LookupManager在非Swing線程環(huán)境中孵化自己的線程是完全沒有必要的,比如一個(gè)非繪圖的用戶界面,在我們的例子中,就是Logger。產(chǎn)生不必要的新線程將損害到你應(yīng)用的性能,而不是提高性能。LookupManager執(zhí)行的很好,不管Swing線程與否--所以,我喜歡把代碼集中在那兒。
現(xiàn)在我們需要將JButton的ActionListener執(zhí)行l(wèi)ookup的代碼放在一個(gè)非Swing線程中。我們創(chuàng)建一個(gè)匿名的Thread,使用一個(gè)匿名的Runnable執(zhí)行這個(gè)lookup。
- private void searchButton_actionPerformed() {
- new Thread(){
- public void run() {
- lookupManager.lookup(searchTF.getText());
- }
- }.start();
- }
這就完成了我們的Swing線程。簡(jiǎn)單地在actionPerformed()方法中添加線程,確保監(jiān)聽器在新的線程中執(zhí)行照顧到了整個(gè)線程問題。注意,我們不用處理像第一個(gè)例子那樣的任何問題。通過把時(shí)間花費(fèi)在定義一個(gè)事件驅(qū)動(dòng)的體系,我們?cè)诤蚐wing線程相關(guān)處理上節(jié)約了更多的時(shí)間。
【編輯推薦】