我有两个条件,一个在另一个里面,用布尔来控制它们。基本上,一个用于终止共享,另一个用于侦听连接。用户可以选择禁用共享,在这种情况下,服务器停止侦听但不会终止。如果用户选择终止,则两个布尔值都设置为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
cicle,测试listening
的值。当我将listening
设置为true
时,它应该重新进入第二个while循环并再次开始侦听,因为我确实打开了服务器套接字(尽管它与此无关,我只是说它必须再次初始化,因为我在禁用共享时关闭它)。但是,禁用后,即使调用listening
,它也永远不会租用openConnection()
循环。
有人知道这里有什么问题吗?
答案 0 :(得分:3)
没有足够的代码显示任何错误。但是这里有一些可能会有所帮助的评论。
shutdown
和listening
布尔值都必须为volatile
。线程之间共享的任何字段都需要以某种方式同步,否则其他线程将无法看到对其值的更改。
serverSocket
也需要volatile
,因为它似乎是由openConnection()
的调用者创建的,但在while
循环中使用。您可以考虑在openConnection()
中将活动设置为true,并使serverSocket
完全由接受线程管理。
clientSockets
看起来像是一个集合。这将需要是一个同步连接,因为它看起来好像是由多个线程访问。同样,更好的模式是closeAllClientConnections()
调用只需设置一个布尔值,线程本身就会关闭。这消除了使用集合等的任何竞争条件。
看起来如果你! terminating
你的接受线程会旋转。至少你应该放一些Thread.sleep(100)
或者其他东西来减慢速度。等待/通知甚至会更好。
重要的是要意识到它不是只是关于在线程程序中“同时”发生的事情。它还涉及内存缓存。接受线程可能在一分钟前向clientSockets
ArrayList1
添加了一些内容,如果列表未以某种方式同步,则另一个线程可能看不到这些更改。更糟糕的是,ArrayList
的某些部分可能已在内存中更新,而其他部分可能导致异常。要获得同步集合,您应该创建ArrayList
之类的:
List<...> clientSockets = Collections.synchronizedList(new ArrayList<...>());
听起来你应该阅读一些关于为什么需要同步的文档:
http://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html