多线程/易失性变量/条件/循环的特殊行为(Java)
这是我当前正在构建的网络服务器的片段......
// ...
threadPool = Executors.newCachedThreadPool(); 而(真) if(this.isOn) { try { // 监听传入连接 this.clientSocket = serverSocket.accept(); } catch (IOException e) { System.err.println("日志:>>接受失败!"); 系统.退出(1); } // 一旦建立连接就发送套接字 // 用一个处理程序/处理器到线程池中执行 threadPool.execute(new ClientRequestProcessor(clientSocket)); }
//...
请注意 isOn 变量是一个 VOLATILE 布尔值。
如果我把 if 变成 while...这段代码可以工作...但事实上它不起作用。请问为什么?从逻辑的角度来看,两者都应该有效,即使我在 if 中测试该标志......我是否遗漏了一些东西?
[稍后编辑:]不工作我的意思是...浏览器(例如firefox)无法连接,实际上它一直在尝试但最终超时。再说一遍,如果我将 if(isOn) 更改为 while(isOn) ,它就像一个魅力。
任何建议/想法都非常受欢迎!
PS 我需要这个组合“while(true) if/while(test flag) {...}”,因为服务器可以从 GUI 启动/停止...所以顶层 while(true) 是需要的,所以我可以重新检查我是否处于开启状态(从而监听连接)或者是否处于关闭状态(并且并不真正关心传入连接)。不用说,GUI 的事件处理程序可以随时修改该标志。
Here's a snippet of a web server that I am currently building...
// ...
threadPool = Executors.newCachedThreadPool(); while (true) if(this.isOn) { try { // listen for incoming connection this.clientSocket = serverSocket.accept(); } catch (IOException e) { System.err.println("LOG: >> Accept failed! "); System.exit(1); } // as soon as a connection is established send the socket // with a handler/processor to the thread pool for execution threadPool.execute(new ClientRequestProcessor(clientSocket)); }
//...
Please note that the isOn variable is a VOLATILE boolean.
If I turn the if into a while... this code works... but as it is it doesn't. May I ask why? From a logical point of view both should work, even if I test that flag in an if... am I missing something?!
[Later edit:] By not working I mean... a browser (e.g. firefox) cannot connect, actually it keeps trying but timesout eventually. Again, if I change that if(isOn) into a while(isOn) it works like a charm.
Any suggestions/ideas are more than welcome!!!
P.S. I need this combo "while(true) if/while(test flag) {...}" because the server can be started/stopped from a GUI... so the top level while(true) is kind of needed so I can recheck whether I am on (and thus listening for connections) or if I am off (and don't really care about incoming connections). Needles to say the event handlers of the GUI can modify the flag at anytime.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
更好的解决方案是,当您希望服务器套接字停止时关闭服务器套接字,并在您希望服务器启动时在新线程中启动新的套接字。这样您就可以拒绝新连接,并且在不执行任何操作时不会消耗 CPU。
当 isOn == true 并将其设置为 false 时,它只会在下一个新连接之后不接受连接。 (可能是稍后的任何时间)此外,任何客户端新连接都只会等待调用接受(或最终超时)默认情况下,最多可以有 50 个连接等待接受。
当 isOn == false 时,你的线程将忙于等待,消耗 CPU。我建议您稍微延迟一下,例如 Thread.sleep(250)。这将显着降低 CPU 利用率,但不会过多地延迟重新启动。
顺便说一句:
A better solution is to close the server socket when you want it to stop and start a new one in a new thread when you want it to start. This way you reject new connections and don't consume CPU when its not doing anything.
When isOn == true and you turn it false, it will only not accept connections after the next new connection. (Could be any time later) Additionally any client new connections will just wait for the accept to be called (or eventually timeout) You can have up to 50 connections waiting to be accepted by default.
When isOn == false, your thread will busy wait, consuming a CPU. I suggest you put in a little delay such as Thread.sleep(250). This will cut CPU dramatically, but not delay starting again too much.
BTW:
如果你有 while(true) 然后 if(this.isOn) while 循环无法停止。当 isOn 标志变为 false 时会发生什么。 while 循环永远不会停止,因为它本质上是无限的。插入一个 else 语句使其中断,它应该按预期工作。
如果您取出 if 语句并将其设置为 while(this.isOn),则当 isOn 标志变为 false 时,循环结束。没有无限循环。
这些是我乍一看的想法......
If you have the while(true) and then if(this.isOn) the while loop has no way of stopping. What happens when the isOn flag is turned to false. The while loop never stops because it is essentially made to be infinite. Plug in an else statement to make it break and it should work as expected.
If you take out the if statement and just make it while(this.isOn) then when the isOn flag is turned to false the loop ends. No infinite loop.
Those are my thoughts at first glance ...
我的假设是基于你那里的紧密循环。您的服务器上是否有可能运行该程序的多个实例?如果你将 isOn 设置为 false,if(isOn) 版本不会关闭,而是会永远循环,烧毁你的 CPU。
My assumption would be based on your tight loop there. Is it possible you have multiple instances of the program running on your server? The if(isOn) version will not shut down if you set isOn to false, instead it will simply loop forever burning your CPU.