繁体   English   中英

EDT与主线程之间的通信

[英]Communication between the EDT and main threads

关于我最近从事的一个项目,我一直问很多问题。 这是我所处的场景,任何帮助或指出正确的方向都会有很大帮助...

这是一个由服务器和多个客户端构建的网络程序。 每个客户端都有一个GUI,该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类之间进行通信?

要使用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);
         }
    }
}

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

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

您可以尝试以下方法:

class Player {公共GUI gui;

...

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

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

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

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

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

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

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

与其使用匿名内部类,不如声明一个实现Runnable并具有以GUI实例作为参数的构造函数的类?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM