网络化摇摆游戏中的多线程:使用invokeLater vs locks

Jer*_*Law 6 java networking swing multithreading

我正在编写一个简单的自上而下的太空游戏,并且正在扩展它以允许通过具有多个玩家的网络进行游戏.我已经做了很多阅读,但这是我第一次这样做,我很欣赏一些关于选择合理设计的建议.

我的GUI是使用Swing编写的.每秒30次,一个计时器触发,并根据内存中游戏世界对象中的数据重新绘制我的GUI(基本上是船只和具有位置的射弹等列表).游戏世界的物理更新也使用此计时器进行.因此,对于单人游戏实现,一切都发生在EDT上,这很好.

现在,我有单独的线程处理来自其他玩家的传入数据包.我想根据这些数据包包含的内容更新我的gameWorld对象中的数据.我的问题是,我应该使用invokeLater进行这些更改,还是应该使用锁来避免并发问题?

说明我的意思:

runMethodOfInputThread() {
    while(takingInput) {
        data = receiveAndInterpretIncomingPacket();  // blocks
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                gameWorld.updateWithNewGameInfo(data);
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

VS

runMethodOfInputThread() {
    while(takingInput) {
        data = receiveAndInterpretIncomingPacket();  // blocks
        synchronize (gameWorldLock) {
            gameWorld.updateWithNewGameInfo(data);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

后者还需要在EDT访问gameWorld的任何地方使用类似的同步块,因此在我看来使用invokeLater会更容易实现.但我认为这两种方法都有效吗?是否还有其他重要的优点/缺点?

谢谢,

杰里米

Bre*_*man 1

方法 1 的优点:

  • 最小化复杂性
  • 稳定

通过将对“gameWorld”变量的访问限制为 EDT 线程,不需要锁定机制。并发编程很复杂,要求程序员在访问线程之间共享的对象时在整个源代码库中保持警惕。程序员可能会忘记在某些情况下进行同步,从而导致游戏状态受损或程序失败。

方法 2 的优点:

  • 可扩展性
  • 表现

最大限度地减少 EDT 线程上完成的处理可确保游戏界面和显示保持对用户的响应。方法 1 目前可能有效,但如果 EDT 线程正忙于执行非 UI 处理,则游戏的后续版本将无法扩展到更高级的界面。