2012-06-06 50 views
1

我正在用附帶的GUI(Swing)編寫客戶端應用程序。我的兩個類ClientClass和MainFrame運行不同的線程,但需要相互調用方法。 ClientClass在EventQueue線程(displayGUI())的應用程序生命週期中的某個時間點實例化GUI(MainFrame)。 ClientClass包含許多方法,如recv(),從客戶端類線程調用,更新MainFrame。反過來,MainFrame具有由事件觸發的方法,例如按下一個調用ClientClass中的方法的按鈕。我假設在該示例中處理按鈕按下的令人討厭的方法正在由EventQueue線程調用?如何在GUI線程之間共享信息?

我很確定這種應用程序非常普遍,我很喜歡別人的洞察力。我有一種感覺,我所做的並不是線程安全的,那麼我該如何修復/改進此應用程序的當前模型?

示例代碼:

MainFrame.java:

public MainFrame(ClientClass c) { 
    client = c; 

    // <Misc init code here> 

    btnSend = new JButton("Send"); 
    btnSend.addMouseListener(new MouseAdapter() { 
     @Override 
     public void mouseClicked(MouseEvent arg0) { 
      client.send("Hello!"); 
     } 
    }); 
    btnSend.setBounds(171, 120, 89, 23); 
    contentPane.add(btnSend); 
} 

public void updateElement() { 
    // Update of some element here, called from ClientClass 
} 

ClientClass.java:

private MainFrame mainFrame; 

public ClientClass() { 
} 

public void displayGUI() { 
    final ClientClass c = this; 

    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       mainFrame = new MainFrame(c); 
       mainFrame.setVisible(true); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

public void send(String msg) { 
    // Socket send operations here 
    // Currently called by the GUI's EventQueue thread? 
} 

public void recv() { 
    // Socket recv operations here 
    mainFrame.updateElement(); 
} 
+0

有關併發性的swing教程應該回答您所有的問題:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/ –

回答

2

可以使用SwingUtilities來調用EDT代碼(上UI線程)。

鼠標點擊在UI線程上被調用 - 所以你應該在後臺調用send(如果需要很長時間不阻止UI)。

在您recv方法,你應該在UI線程調用mainFrame.updateElement();如果你改變GUI狀態(JLabel的文本等) - 您可以通過這樣做:

SwingUtilities.invokeLater(new Runnable() {... // 

一般來說 - 任何你可能會影響GUI在美國東部時間你應該做的元素(改變文本,無效,添加組件等)。

而且所有可能阻止用戶界面的東西都應該在後臺執行 - 產生新的Thread

如果你需要阻止任何事件和等待的背景 - 你可以顯示模式JDialog(請記住,你應該把它藏在finally塊 - 以防萬一)

你也應該看看SwingWorker類和tutorial

+0

感謝您的迴應!無論如何在原始線程(ClientClass線程)上調用發送? – Ramsey

+1

您可以使用BlockingQueue,其中GUI將添加要發送的消息。主線程將從這個隊列中獲取消息併發送它們。 –

+1

@JB Nizet評論回答你的問題。您還應該查看http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService。html – Xeon

3

至少在這種情況下,Xeon的答案可能對你更直接有用,但作爲一般委託人,你可能需要閱讀Singletons

通過創建一個單一的Singleton(在你描述的情況下,它通常被稱爲Manager或some-such),你可以有一個類來執行與你的應用程序相關的'工作',並且有GUI線程(s)發送任務給那個單身人士。