JavaSwingGUI冻结

JavaSwingGUI冻结,java,swing,sockets,user-interface,concurrency,Java,Swing,Sockets,User Interface,Concurrency,我正在使用套接字编写Java客户端/服务器GUI应用程序,问题是: 我有一个按钮开始侦听指定端口: 按钮动作执行方法 private void listenButtonActionPerformed(java.awt.event.ActionEvent evt) { int port = Integer.parseInt(portTextfield.getText(), 10); try

我正在使用套接字编写Java客户端/服务器GUI应用程序,问题是:

我有一个按钮开始侦听指定端口:

按钮动作执行方法

private void listenButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
    int port = Integer.parseInt(portTextfield.getText(), 10);

    try {
        socket.listen(port);
    } catch (IOException ex) {
    }
}
这是socket.listen方法

public static void listen() throws IOException {
    ServerSocket ss = new ServerSocket(port);

    while (true)
        new socket(ss.accept());
}
“套接字”类扩展了“线程”
因此,在ss.accept()返回一个值后,它将在单独的线程中创建新的套接字实例


单击按钮后,GUI冻结,因为在socket.listen方法中有一个无限循环。如何避免这种情况?

您需要使用多线程。如果我在你的位置,我会分离GUI代码和服务器代码,当按下按钮时,我只是将服务器代码作为一个新线程启动

您的代码基本上冻结了GUI,因为所有事件都是在事件调度程序线程(EDT)上执行的,EDT是负责所有GUI内容和相应事件的线程。如果您阻止它、停止它或抛出循环,它将影响其性能。

请检查以下内容:

1) 若您正在编写GUI应用程序,则可能处于Swing状态,请不要调用 事件调度程序线程或事件处理程序中的阻塞方法。 例如,如果您正在读取文件或打开网络连接 单击按钮时,不要在actionPerformed()方法上执行该操作, 相反,只需创建另一个工作线程来完成该任务并返回 从actionPerformed()。这将使您的GUI保持响应性,但同样如此 这取决于设计,如果操作需要 用户等待,而不是考虑使用同步调用 更新


使用多线程:

您的设计中有两个陷阱:

  • ss.accept()
    是一个阻塞调用,因此您的UI将冻结,直到有传入连接
  • 切勿在EDT中循环(true)时运行
    
    相反,请执行以下操作:

    • 单击按钮时,创建一个线程,该线程将开始侦听传入的连接
    • 每当您有一个传入连接时,创建另一个线程,该线程将接受传入的客户端连接并处理它
    只要您的

    new socket(ss.accept());
    
    立即返回,您只需更改

    while (true)
    
    这将EDT(事件调度线程)放入一个无限循环,您的GUI变得不负责任。所以,删除这一行

    如果不能,则使用SwingWorker类() 创建扩展SwingWorker的嵌套类。只需调用swingWoker.execute();(创建其对象后)在ListenButtoActionPerformed(java.awt.event.ActionEvent evt)方法中

    请参见教程:

    永远不要创建新线程并从Swing EDT运行它

    试试这些

    1。在获取初始连接期间,可能会发生延迟,因此首先创建并清空
    套接字,然后尝试连接到服务器。

       `Socket s = new Socket();`
    
       `s.connect(new InetSocketAddress("ip_addr",port_nos),1000);`
    
    2。其次,始终将非UI工作排除在UI线程之外。

    下面是我的服务器-客户端通信示例

    客户端代码:

    public class ClientWala {
    
        public static void main(String[] args) throws Exception{
    
            Boolean b = true;
        Socket s = new Socket();
        s.connect(new InetSocketAddress("127.0.0.1", 4444),1000);
    
        System.out.println("connected: "+s.isConnected());
    
    
        OutputStream output = s.getOutputStream();
        PrintWriter pw = new PrintWriter(output,true);
    
        // to write data to server
        while(b){
    
            if (!b){
    
                 System.exit(0);
            }
    
            else {
                pw.write(new Scanner(System.in).nextLine());
            }
        }
    
    
        // to read data from server
        InputStream input   = s.getInputStream();
        InputStreamReader isr = new InputStreamReader(input);
        BufferedReader br = new BufferedReader(isr);
        String data = null;
    
        while ((data = br.readLine())!=null){
    
            // Print it using sysout, or do whatever you want with the incoming data from server
    
        }
    
    
    
    
        }
    }
    
    服务器端代码:

    import java.io.*
    import java.net.*;
    
    
    public class ServerTest {
    
        ServerSocket s;
    
        public void go() {
    
            try {
                s = new ServerSocket(44457);
    
                while (true) {
    
                    Socket incoming = s.accept();
                    Thread t = new Thread(new MyCon(incoming));
                    t.start();
                }
            } catch (IOException e) {
    
                e.printStackTrace();
            }
    
        }
    
        class MyCon implements Runnable {
    
            Socket incoming;
    
            public MyCon(Socket incoming) {
    
                this.incoming = incoming;
            }
    
            @Override
            public void run() {
    
                try {
                    PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
                            true);
                    InputStreamReader isr = new InputStreamReader(
                            incoming.getInputStream());
                    BufferedReader br = new BufferedReader(isr);
                    String inp = null;
    
                    boolean isDone = true;
    
                    System.out.println("TYPE : BYE");
                    System.out.println();
                    while (isDone && ((inp = br.readLine()) != null)) {
    
                        System.out.println(inp);
                        if (inp.trim().equals("BYE")) {
                            System.out
                                    .println("THANKS FOR CONNECTING...Bye for now");
                            isDone = false;
                            s.close();
                        }
    
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    try {
                        s.close();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                    e.printStackTrace();
                }
    
            }
    
        }
    
        public static void main(String[] args) {
    
            new ServerTest().go();
    
        }
    
    }
    

    你的问题是什么…,为了更好的帮助,请尽快发布一个SSCCERead。作为参考,这里有一个工作示例。