【问题标题】:Client-Server Java GUI: read/write causing program to freeze客户端-服务器 Java GUI:读/写导致程序冻结
【发布时间】:2013-12-16 20:04:45
【问题描述】:

我正在用 Java 编写客户端/服务器程序(包括 GUI)。 我在客户端有以下代码:

public class SBListener implements ActionListener{
  public void actionPerformed(ActionEvent e){
     try{
        outToServer.writeUTF(usn.getText().trim());
        System.out.println("sent username to server");
        playerExists = inToClient.readBoolean();
        System.out.println("past getting player");
        System.out.println("player exists = " + playerExists);
     }catch(IOException a){
        System.err.println(a);
     }
     if(playerExists == false){
        JButton submitInfo = new JButton("submit info");
        submitInfo.addActionListener(new SBNewInfoListener());
        init.add(new JLabel(""));//dummy element to get the right alignment
        init.add(new JLabel("First Name:"));
        init.add(fn);
        init.add(new JLabel("Last Name:"));
        init.add(ln);
        init.add(submitInfo);
        add(init, BorderLayout.WEST);
        init.setVisible(true);
        init.revalidate();
        init.repaint();
     }

  }

}

服务器中的代码如下:

String username = inp.readUTF();
System.out.println(username);
out.writeBoolean(false);

System.out.println("wrote boolean, waiting for fn/ln/un");
fn = inp.readUTF();
System.out.println("got fn");
ln = inp.readUTF();
un = inp.readUTF();

但是当单击调用 SBListener 的按钮时,程序会在到达服务器等待 fn/ln/username 的位置时冻结。我添加了一堆用于调试的 system.out 语句,然后我开始使用“写布尔值,等待 fn/ln/un”的语句。

基本上,我试图在服务器返回 false 值后更新屏幕。具体来说,我想为名字和姓氏添加两个文本字段。然后我想将这些值发送到服务器。

谁能告诉我如何解决这个问题?提前感谢您的帮助!

【问题讨论】:

    标签: java swing client-server event-dispatch-thread


    【解决方案1】:

    不要在 ActionListener 中执行客户端/服务器代码。这将导致事件调度线程在等待来自服务器的响应时阻塞。当 EDT 被阻止时,整个 GUI 冻结。

    阅读 Concurrency 上的 Swing 教程部分了解更多信息。您需要为客户端/服务器代码使用单独的线程。或者您可以使用教程中讨论的SwingWorker

    【讨论】:

    • 谢谢!我重组了我的代码,使得 ActionListeners 不包含客户端/服务器代码。如果你有时间,我还有一个与此相关的问题:当用户单击一个按钮时,我可以从该按钮的 ActionListener 向客户端/服务器线程发出信号,告诉它发送 fn/ln 到服务器吗?如果这会让事情更清楚,我可以添加代码。
    • @user3107593 一般的答案是肯定的,但这是一个围绕监视器和同步块的相关主题,这可能在 cmets 范围内无法回答。而是阅读Concurrency 上的一般部分,如果您遇到困难,请发布另一个问题
    【解决方案2】:

    我的猜测是outToServer 没有被刷新。我猜(虽然我无法从您的示例代码中看出)outToServerDataOutputStream。您需要调用.flush 以将数据从缓冲区中取出并传输到线路上。

    试试这个:

    outToServer.writeUTF(usn.getText().trim());
    outToServer.flush();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-26
      • 2013-07-03
      • 1970-01-01
      • 2016-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-19
      相关资源
      最近更新 更多