EDT和主线程之间的通信

时间:2009-04-16 03:59:05

标签: java multithreading swing event-dispatch-thread

我一直在询问有关我最近一直在做的项目的很多问题。这是我所处的情景,正确方向的任何帮助或观点都会有所帮助......

这是一个使用服务器和多个客户端构建的网络程序。每个客户端都有一个GUI,必须根据服务器发送的命令执行操作。每个客户端都包含在一个名为Player的类中。这个Player有一个GUI(扩展JFrame)和一个main方法,而Server只有一个main方法(没有GUI)。起初,这个类是在主线程中创建的,如下所示:

EventQueue.invokeLater(new Runnable()
{
    public void run()
    {
        new Player().setVisible(true);
    }
 });

这很好用,直到我意识到整个Player类现在正在EDT中执行。因此,当我等待来自服务器的命令时,整个GUI会锁定,直到发送该命令并执行适当的操作。你可以想像,这是一个可怕的设计,并被证明是一个编码环境的真正的痛苦时,每次要检查的东西,你必须找到周围一些疯狂的工作,使GUI依然保持完好。

显然,我必须在单独的线程中检查来自服务器的命令,并在EDT中运行GUI组件。我的第二个实现有两个类 - 一个用于GUI,一个用于Player。我的想法是Player有一个包含GUI的变量,以便我可以从Player类访问GUI,如下所示:

class Player
{
    public GUI gui;

    ...

    // And then start this gui inside of the EDT.
    EventQueue.invokeLater(new Runnable()
    {
         public void run()
         {
              this.gui = new GUI().setVisible(true);
         }
    }

这也不起作用,因为新this对象内的Runnable引用了Runnable对象,而不是Player

如何在一个线程中的Player类与EDT线程中相应的GUI类之间进行通信?

6 个答案:

答案 0 :(得分:3)

要使用this指针处理问题,您应该写:

class Player
{
    public GUI gui;

    ...

    // And then start this gui inside of the EDT.
    EventQueue.invokeLater(new Runnable()
    {
         public void run()
         {
              Playser.this.gui = new GUI().setVisible(true);
         }
    }
}

答案 1 :(得分:2)

BorisPavlović语法正确(实际上您可以删除this.),但代码仍然没有意义。 gui字段在Runnable事件排队后的某个时间初始化,因此播放器线程使用它是不安全的。

您可以在EDT上构建Player(但在EDT上执行网络操作)。或者将GUI注册为Player的监听器(观察者)。 invokeAndWait会起作用,但是很危险,因为它经常会导致偶尔难以调试的死锁。

答案 2 :(得分:1)

答案 3 :(得分:1)

你可以试试这个:

班级球员 {     公共桂桂;

...

// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
     public void run()
     {
          Player.this.gui = new GUI().setVisible(true);
     }
}

答案 4 :(得分:1)

“直到我意识到整个Player类现在正在EDT中执行”

构造函数出现在EDT上,但在此类上调用的方法可能不是。

您应该按照最初的意图构建播放器GUI。

 EventQueue.invokeLater(new Runnable() 
 {
    public void run()
    {
        new Player().setVisible(true);
    }
 });

但是Player可以在构造函数中启动一个单独的线程(我个人在玩家之间共享一个连接)。

当然,服务器的回调方法在修改可见组件时应使用invokeLater()。

答案 5 :(得分:0)

为什么不将匿名内部类声明为实现Runnable的类,而是使用一个以GUI实例作为参数的构造函数,而不是使用匿名内部类?

此外,如果您的GUI类不是线程安全的,请考虑使用消息队列在EDT和&之间进行通信。主线。