2012-06-06 49 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)发送任务给那个单身人士。