使用用户界面(Swing)在Java上启动ServerSocket冻结

美好的一天,

我有一个无限循环的ServerSocket,工作正常…问题是当我尝试用一​​个按钮启动ServerSocket。 我的用户界面“Freeze”不动,什么,但是服务器很好,这里我有一个ScreenShot

http://sofzh.miximages.com/java/15d331166dd3f651fc7bda4e3670be4d.png

当我按下按钮“Iniciar”意味着启动服务器,用户界面冻结(ServerSocket无限循环)。 我无法更改我的代码,因为它的工作正常。

public static void iniciarServer() { try { appendString("\nServidor iniciado."); System.out.println("asdasd"); } catch (BadLocationException e1) { e1.printStackTrace(); } try { ss = new ServerSocket(1234, 3); while (true) { System.out.println("Esperando conexiones..."); appendString("\nEsperando conexiones..."); Socket s = ss.accept(); System.out.println("Conexión entrante: " + s.getRemoteSocketAddress()); appendString("\nConexión entrante: " + s.getRemoteSocketAddress()); conexiones++; //System.out.println("Debug: conexiones SERVER: " + conexiones); MultiThread mt = new MultiThread(s, conexiones); mt.start(); /////////////////////////////////////////////////////////////// } } catch (IOException e) { System.out.println("Error Server: " + e.getMessage()); } catch (BadLocationException e) { e.printStackTrace(); } stopServer(); } 

appendString(); 用于向JTextPane添加一些文本,但由于UI冻结而无效。

有没有办法做一个不被无限循环冻结的用户界面?

谢谢!

Swing是一个单线程框架,这意味着在事件调度线程的上下文中执行的任何阻塞或长时间运行操作都将阻止它处理事件队列,从而使您的应用程序挂起。

它也不是线程安全的,所以你永远不应该尝试修改EDT外部的任何UI组件的状态。

有关更多详细信息,请查看Swing和工作线程中的并发 和SwingWorker

 public class ServerSocketWorker extends SwingWorker { private JTextArea ta; public ServerSocketWorker(JTextArea ta) { this.ta = ta; } @Override protected void process(List chunks) { for (String text : chunks) { ta.append(text); } } @Override protected Void doInBackground() throws Exception { ss = new ServerSocket(1234, 3); while (true) { publish("\nEsperando conexiones..."); Socket s = ss.accept(); publish("\nConexión entrante: " + s.getRemoteSocketAddress()); conexiones++; //System.out.println("Debug: conexiones SERVER: " + conexiones); MultiThread mt = new MultiThread(s, conexiones); mt.start(); /////////////////////////////////////////////////////////////// } } @Override protected void done() { stopServer(); //?? } } 

要启动它,你可以使用像……

 public void iniciarServer() { ServerSocketWorker worker = new ServerSocketWorker(textAreaToAppendTo); worker.execute(); } 

举个例子

ServerSocket.accept()方法是一种阻塞方法。 这意味着Socket s = ss.accept(); 停止当前线程,直到打开与服务器套接字的连接。

Swing中的事件调度是单线程的,上面提到的while循环和阻塞操作将使线程“忙”并阻止与UI的所有其他交互。

您应该在一个单独的线程中运行整个while循环。 当您想要停止服务器时,还应该确保退出while循环并且线程完成执行。