java - 为什么不重新评估 while 条件?

标签 java multithreading sockets loops while-loop

我有两个 while 条件,一个在另一个里面,用 boolean 值来控制它们。基本上,一个用于终止共享,另一个用于监听连接。用户可以选择禁用共享,在这种情况下,服务器会停止监听但不会终止。如果用户选择终止,则两个 boolean 值都设置为 false,循环结束。

这是我的代码:

        public void run() {
            while (!terminate) {  
                while (listening) {
                    try {
                        // accept connection -> create a new thread for each client
                        ClientServerShareInstance clientServerShareInstance = new ClientServerShareInstance(serverSocket.accept(), ui);
                        Thread clientServerThread = new Thread(clientServerShareInstance);
                        clientSockets.add(clientServerShareInstance);
                        connectedClients++;
                        clientServerThread.start();
                    } catch (IOException ex) {
                    }
                }
            }
        }

        public void closeAllClientConnections() {
            for (Iterator it = clientSockets.iterator(); it.hasNext();) {
                ClientServerShareInstance clientServerShareInstance = (ClientServerShareInstance) it.next();
                clientServerShareInstance.closeAllConnections();
                it.remove();
            }
            try {
                this.serverSocket.close();
            } catch (IOException ex) {}
            this.setActive(false);
            this.connectedClients = 0;
        }


        public void openConnection() {
            try {
                serverSocket = new ServerSocket(portNumber, 0, Inet4Address.getLocalHost());
                setActive(true);
            } catch (IOException ex) {}
        }
    }

closeAllClientConnections() 方法禁用共享(不终止它),openConnection() 重新启用该共享。

问题是,如果我禁用共享,它应该无限期地循环 terminate while cicle,测试 listening 的值。当我将 listening 设置为 true 时,它应该重新进入第二个 while 循环并再次开始监听,因为我确实打开了服务器套接字(尽管与此无关,我只是说它必须再次初始化,因为我在禁用共享时关闭了它)。但是,禁用后,它永远不会租用 listening 循环,即使在调用 openConnection() 时也是如此。

有人知道这里出了什么问题吗?

最佳答案

显示的代码不足,无法显示任何错误。但这里有一些评论可能会有所帮助。

  • shutdownlistening boolean 值都必须是volatile。线程之间共享的任何字段都需要以某种方式同步,否则其他线程将看不到对其值的更改。

  • serverSocket 也需要是 volatile 因为它似乎是由 openConnection() 的调用者创建但在while 循环。您可能会考虑在 openConnection() 中将 active 设置为 true,并让 serverSocket 完全由接受线程管理。

  • clientSockets 看起来是一个集合。这将需要是一个同步连接,因为它看起来像是被多个线程访问。同样,更好的模式是 closeAllClientConnections() 调用 只是 设置一个 boolean 值,线程本身将执行关闭操作。这消除了围绕使用集合等的任何竞争条件。

  • 如果您是 ,看来是这样!终止 您的接受线程将旋转。至少你应该放一些 Thread.sleep(100) 或其他东西来减慢它的速度。等待/通知会更好。

重要的是要认识到,线程程序中“同时”发生的事情不只是。它还与内存缓存有关。 accept 线程可能在一分钟前向 clientSockets ArrayList1 添加了一些内容,如果列表未以某种方式同步,则另一个线程可能看不到这些更改。更糟糕的是 ArrayList 的某些部分可能已在内存中更新,但其他部分未更新,这可能会导致异常。要获得同步集合,您应该像这样创建 ArrayList:

List<...> clientSockets = Collections.synchronizedList(new ArrayList<...>());

听起来你应该阅读一些关于为什么需要同步的文档:

http://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html

关于java - 为什么不重新评估 while 条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10949348/

相关文章:

java - 线程, volatile 变量不更新

c - 使用 TCP 通过套接字传输文件时卡住

java - 如何正确使用带套接字的 HandlerThread?

java - Spring 与 Hibernate - 发现预绑定(bind) JDBC 连接

java - JSF 2 - f :selectItems with a Date keyed Map

multithreading - 使用2个线程在串口上同时读写

multithreading - 这个读写器锁实现正确吗?

c# - 使用 C# 进行套接字编程

java - 是否有一种简单的方法来创建给定函数和一组参数的反向映射?

java - 如何在现有项目中正确使用 Swagger Maven Plugin