我有两个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()
循环。有人知道这是怎么回事吗?
最佳答案
没有足够的代码显示以显示任何错误。但是,以下一些评论可能会有所帮助。
shutdown
和listening
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<...>());
听起来您应该阅读一些有关为什么需要同步的文档: