繁体   English   中英

在Java中搜索无限循环的替代方案

[英]Searching for alternative to endless loop in Java

我正在做我的家庭作业,这是关于聊天程序。 它有两个接口,一个用于服务器,第二个用于客户端。 程序流程如下:

  1. 服务器在某个端口上启动连接
  2. 客户端启动并尝试连接到服务器
  3. 如果一切正常,他们就开始聊天了
  4. 其中一个终端类型“TERMINATE”会话将结束。

该程序源自Deitel&DeitelJava How To Program 6e书。 该示例每个接口只有两个元素:用于显示消息的displayArea(JTextArea)和用于输入消息的输入(JTextField)。

Enter键会将消息发送到其他人。

Server.java的一段代码如下。 它在无限循环中执行一些重复操作。

public void runServer() {
    // set up server to receive connections; process connections
    SwingUtilities.invokeLater(new Runnable() {

        public void run() 
        {
            try {

                // Step 1: Create a ServerSocket.
                String portNum = txtPort.getText();
                server = new ServerSocket(Integer.parseInt(portNum), 100);

                InetAddress ip = InetAddress.getLocalHost();
                txtServerIP.setText(ip.getHostAddress());

                while (true) {

                    try {
                        waitForConnection(); // Step 2: Wait for a connection.
                        getStreams(); // Step 3: Get input & output streams.
                        processConnection(); // Step 4: Process connection.
                    }
                    // process EOFException when client closes connection
                    catch (EOFException eofException) {
                        System.err.println("Client terminated the connection.");
                    }
                    finally {
                        closeConnection(); // Step 5: Close connection.
                        ++counter;
                    }
                } // end while
            } // end try
            // process problems with I/O
            catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    });
} // end method runServer

它适用于原始代码。 我决定在接口中添加一些GUI元素,并使用Eclipse Luna 4.4.1添加了一个Application窗口。 我添加了IP地址和端口号的输入。 然后我为Server GUI添加了一个“Open Connection”按钮,为Client GUI添加了另一个“Connect to the Server”按钮。

现在我运行Server.java,直到我点击“打开连接”按钮。 然后按钮保持按下,尽管我发布并且表单没有响应。 之后我运行Client.java并连接到服务器并从服务器获取“连接成功”消息。 我发送一些消息后关闭客户端窗口,然后突然所有消息都出现在服务器窗口上。

现在我明白服务器窗口的非响应是因为while ( true )循环。 换句话说,该程序运行良好,但无法足够快地更新界面。 我想用一个端口监听器来改变它,或者更快或更敏感的其他东西。

我该怎么改变它?

我变了

public void runServer() {
    // set up server to receive connections; process connections
    SwingUtilities.invokeLater(new Runnable() {...

public void runServer() {
    // set up server to receive connections; process connections
    SwingUtilities.invokeLater(new Thread() {...

但情况仍然不变。

您可以访问我的代码

ServerGUI.java @ http://pastebin.com/pVRi6EfC

ClientGUI.java @ http://pastebin.com/HfftM159

原始代码:

Server.java @ http://pastebin.com/6Q5Z00gb

Client.java @ http://pastebin.com/uCGFGknf

问题是您使用的是SwingUtilities.invokeLater 正如这个答案所解释的那样, invokeLater在应用程序的主Thread执行run体。 由于您的UI也在此Thread运行,因此您需要使用其他方法。

你需要将这个无限循环放在一个Thread中并明确地调用start这样它就不会阻塞你的UI。

class MyChatServer extends Thread {
    public void run() {
        // the while loop
    }
}

然后,您可以在按下“打开连接”按钮时启动Thread

MyChatServer server = new MyChatServer();
server.start();

如果没有显式创建新的Thread ,您的应用程序将只有一个Thread Thread将在UI和您需要执行的任何其他工作之间共享。 所以,当你有一些工作(比如你的while(true) )会占用你唯一的Thread ,你的UI会冻结,直到再次给予控制权。

因此,通过创建新的Thread ,您允许UI保持控制而不是冻结。

您的无限循环是忙碌的等待,这会阻止您的UI刷新。 你有两个问题:

  • 忙碌的等待不是最好的方法
  • 等待阻止UI实现和事件处理

请寻找替代方案 ,而不是忙着等待。

此外,您应该在引擎的不同线程中使用UI。 您可能还想阅读有关swing并发性的内容

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM