我有两个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()重新启用该共享。

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

有人知道这是怎么回事吗?

最佳答案

没有足够的代码显示以显示任何错误。但是,以下一些评论可能会有所帮助。

  • shutdownlistening boolean 值都必须为volatile。线程之间共享的任何字段都需要以某种方式进行同步,否则其他线程将看不到对其值的更改。
  • serverSocket也将需要是volatile,因为它似乎是由openConnection()的调用者创建的,但在while循环中使用了。您可能会考虑将openConnection()中的active设置为true,并让serverSocket完全由接受线程来管理。
  • clientSockets看起来是一个集合。这将需要是一个同步连接,因为同样,它看起来像是由多个线程访问的。同样,更好的模式是让closeAllClientConnections()调用仅设置一个 boolean 值,而线程本身将完成关闭。这样就消除了使用集合等的任何竞争条件。
  • 看起来是,如果您是! terminating,那么您的接受线程将旋转。至少您应该放置一些Thread.sleep(100)或其他东西来减慢它的速度。等待/通知甚至会更好。

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

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

    10-08 19:29