[英]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.