1

我正在为一个学校项目制作网络战舰游戏。GUI 具有一个 JButtons用作游戏板的网格。当用户点击一个按钮时,它会调用sendShot()下面的方法。此方法将他们的镜头发送到远程机器,远程机器检查它是命中还是未命中并返回结果。然后第一台机器接收该结果并相应地更新其 GUI。我在下面的代码正在执行此操作,但我的问题是直到另一台机器发送下一个镜头之后,GUI 才会更新。我猜这是因为我是recieveShot()sendShot()方法内部调用的,但我不是 100% 清楚为什么,因为更新 GUI ( gp.ob.updateBoard(sr))) 的方法是在之前调用的receiveShot()。我在这里有什么误解?

此外,我觉得我这里的基本程序流方法有缺陷,receiveShot()不应该从sendShot()方法中调用。这个方案有什么明显的替代方案吗?

void sendShot(ShotAttempt sa){

    try {
       oos.writeObject(sa);
       oos.flush();
       System.out.println("shot fired");
       ShotResult sr = (ShotResult)ois.readObject();
       gp.ob.updateBoard(sr); 
    } catch (IOException | ClassNotFoundException e) {
        System.out.println(e.printStackTrace());}
      receiveShot();
}

void receiveShot(){
    try{
    ShotAttempt sa = (ShotAttempt)ois.readObject();
    ShotResult sr = gp.db.acceptShot(sa);
    oos.writeObject(sr);
    oos.flush();
    } catch (IOException | ClassNotFoundException e){e.printStackTrace();}
}
4

1 回答 1

2

直到另一台机器发送下一个镜头后,GUI 才会更新。我猜这是因为我在 sendShot() 方法中调用了 recieveShot(),但我不是 100% 清楚为什么,因为更新 GUI 的方法 (gp.ob.updateBoard(sr)) ) 在 receiveShot() 之前调用。

receiveShot()方法阻塞 Swing 事件调度线程或 EDT。由于该线程负责所有 Swing 图形、用户交互和 Swing 事件处理,因此不会处理在事件线程上排队和等待处理的 Runnable,即使它们在receiveShot()调用方法之前已排队。它们只能在线程被解除阻塞时处理,这将在你收到一个镜头之后。

建议:

  • 您应该在后台线程上进行所有套接字通信。
  • 我会创建程序状态,可能由一个枚举持有,比如称为 State,并给它至少两个可能的值,SHOOTING 和 RECEIVING。
  • 在发送一个镜头后适当地设置您的状态为 State.RECEIVING。
  • 接球后设置回 State.SHOOTING。
  • 不允许玩家在接球状态下投篮。这样,您的代码将不需要阻止方法来阻止用户拍摄。
  • 您也可以将 END_GAME 作为您的状态之一。
  • 我会给我的班级一个setState(State state)方法。
  • 在这种方法中,我可以根据新状态启用/禁用我的拍摄按钮。
  • 您将需要一个后台线程,可能是 SwingWorker,持续运行,在套接字上侦听消息。当这个线程接收到它已经被击中的信息时,它会通过调用来更新程序的状态setState(newState)
  • 我会注意在 Swing 事件线程上调用 setState,以便状态更改全部由一个线程完成。
  • 然后我会在一个单独的后台线程上调用拍摄,但它只存在用于拍摄。它不会连续运行。

有关 Swing 事件调度线程的更多信息,请查看Swing 中的并发

于 2013-05-22T01:43:51.783 回答