while(true)ServerSocket Listen的效率

我想知道一个典型的while(true) ServerSocket监听循环是否需要整个核心等待并接受客户端连接(即使实现runnable并使用Thread .start()

我正在实现一种分布式计算集群,每台计算机都需要它用于计算的每个核心。 主节点需要与这些计算机通信(调用修改算法function的静态方法)。

我需要使用套接字的原因是由于跨平台/跨语言function。 在某些情况下,PHP将调用这些java静态方法。

我使用了一个java profiler(YourKit),我可以看到我正在运行的ServerSocket监听线程,它永远不会睡觉而且它总是在运行。 有没有更好的方法来做我想要的? 或者,性能影响是否可以忽略不计?

如果你能想到一个更好的方法,请随时提供任何建议(我已尝试过RMI,但不支持跨语言。

感谢大家

如果你的意思是这样的:

 while (true) { Socket socket = server.accept(); /* Do something with socket... */ } 

然后,不,对accept()的调用不会“占据整个核心”。 这是一个阻塞调用,允许在另一个线程上调度CPU,直到客户端实际连接为止。 一旦对accept()的调用返回,当前线程将被调度为运行并将消耗CPU,直到它在循环的下一次迭代中阻塞在accept()上。

为了避免其他客户端的监听积压过大,另一个线程通常会处理与新接受的Socket交互,让一个线程专注于接受新客户端。 套接字处理线程可能使用NIO处理许多套接字,或者它可能专用于单个套接字,这对于编码来说要简单得多,但在数百个并发连接之后不能很好地扩展。

您可能希望查看Java 1.4 nio库,特别是ServerSocketChannel。 我非常成功地使用它来实现一个高效的服务器,代码的关键部分是:

 Selector selector = Selector.open(); ServerSocketChannel server= ServerSocketChannel.open(); server.socket().bind(new java.net.InetSocketAddress(port)); server.configureBlocking(false); SelectionKey serverKey = server.register(selector, SelectionKey.OP_ACCEPT); // start listening thread new Thread(listener).start(); 

并且监听器只是一个运行的循环:

 selector.select(1000); // listen for one second max Set keys = selector.selectedKeys(); if (keys.size()>0) { handleKeys(keys); } 

我使用了一个java profiler(YourKit),我可以看到我正在运行的ServerSocket监听线程,它永远不会睡觉而且它总是在运行。

基本上,分析器会误导你。

我假设您的代码如下所示:

 ServerSocket server = ... // configure server socket try { while (true) { Socket socket = server.accept(); // do something with socket (and close it afterwards!) } } catch (InterruptedException ex) { // we're outta here! } 

这不会占用大量的CPU …除非你做了一些病态的事情,比如用一个小的超时调用ServerSocket.setSoTimeout(int)

让核心睡一会儿。 在Runnable方法中,添加类似的内容

 Thread.sleep(250); // milliseconds 

在每个循环中。

这应该会显着降低CPU使用率

编辑:坏主意,看评论,对不起,我的错


并且:不要使用while(true)。 这是一个糟糕的设计,因为语义表明最终真实不再是真实的。 通常,您需要从主线程查询一些volatile或primefaces变量

 public class MyClass { class MyRunnable implements Runnable { public void run() { while (MyClass.this.keepGoing.get()) { // listen(); try { Thread.sleep(500); } catch (InterruptedException e) { // deal with exception } } } } private final AtomicBoolean keepGoing = new AtomicBoolean(true); } 

这样主线程就有办法停止监听器线程。