EDT 和主线程之间的通信
-
09-09-2019 - |
题
我一直在问很多关于我最近正在进行的项目的问题。这是我所处的场景,任何帮助或指出正确方向都会有很大帮助......
这是一个由一个服务器和多个客户端构建的网络程序。每个客户端都有一个 GUI,它必须根据服务器发送的命令进行操作。每个客户端都包装在一个名为的类中 Player
. 。这 Player
有一个 GUI(扩展 JFrame
)和一个 main 方法,并且服务器只有一个 main 方法(没有 GUI)。最初,这个类是在主线程中创建的,如下所示:
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new Player().setVisible(true);
}
});
这工作得很好,直到我意识到整个 Player
类现在正在 EDT 中执行。因此,当我等待来自服务器的命令时,整个 GUI 会锁定,直到发送该命令并执行正确的操作。正如您可以想象的那样,这是一个可怕的设计,并且被证明是编码环境的真正痛苦,因为每次您想要检查某些内容时,您都必须找到一些疯狂的解决方案,以便 GUI 仍然保持完整。
显然,我必须在单独的线程中检查来自服务器的命令,并在 EDT 中运行 GUI 组件。我的第二个实现有两个类 - 一个用于 GUI,一个用于 Player
. 。我们的想法是 Player
有一个保存 GUI 的变量,以便我可以从 Player
类,像这样:
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);
}
}
}
鲍里斯·帕夫洛维奇得到语法正确的(实际上,你可以只取出this.
),但仍是代码没有意义。所述gui
字段有时初始化的Runnable
事件排队之后,所以它是不安全的玩家线程来使用它。
您可以构建在EDT Player
(但做网络运营断EDT)。或注册的Player
的GUI作为侦听器(观察者)。 invokeAndWait
会的工作,但是是危险的,因为它往往会导致偶尔难以调试僵局。
您可以试试这个:
类播放机 { 公共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);
}
});
但玩家可以在构造函数(我个人倒分享玩家之间的连接)。
启动一个单独的线程当然,来自服务器的回调方法应该修改可见组件时使用的invokeLater()。
代替使用一个匿名内部类的,为什么不声明一个类的实现Runnable和具有一个构造函数的GUI实例作为自变量?
此外,如果您的GUI类不是线程安全,可以考虑使用一个消息队列中的EDT&主线程之间进行通信。