while(true)ServerSocket Listen的效率

时间:2022-03-23 05:11:19

I am wondering if a typical while(true) ServerSocket listen loop takes an entire core to wait and accept a client connection (Even when implementing runnable and using Thread .start())

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

I am implementing a type of distributed computing cluster and each computer needs every core it has for computation. A Master node needs to communicate with these computers (invoking static methods that modify the algorithm's functioning).

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

The reason I need to use sockets is due to the cross platform / cross language capabilities. In some cases, PHP will be invoking these java static methods.

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

I used a java profiler (YourKit) and I can see my running ServerSocket listen thread and it never sleeps and it's always running. Is there a better approach to do what I want? Or, will the performance hit be negligible?

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

Please, feel free to offer any suggestion if you can think of a better way (I've tried RMI, but it isn't supported cross-language.

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

Thanks everyone

感谢大家

4 个解决方案

#1


8  

If you mean something like this:

如果你的意思是这样的:

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

then, no, the call to accept() does not "take an entire core." It's a blocking call that will allow the CPU to be scheduled for another thread until a client actually connects. Once the call to accept() returns, the current thread will be scheduled to run and will consume CPU until it blocks on accept() in the next iteration of the loop.

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

To avoid the listen backlog of other clients growing too large, another thread usually handles interaction with the newly-accepted Socket, leaving one thread to focus on accepting new clients. The socket handling thread might handle many sockets, using NIO, or it might be dedicated to a single socket, which is much simpler to code but won't scale well past many hundreds of simultaneous connections.

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

#2


5  

You might want to take a look at the Java 1.4 nio libraries and in particular ServerSocketChannel. I use this very successfully to implement an efficient server, the key bits of code are:

您可能希望查看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();

And the listener is just a loop that runs:

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

selector.select(1000); // listen for one second max
Set<SelectionKey> keys = selector.selectedKeys();

if (keys.size()>0) {
    handleKeys(keys);
}

#3


3  

I used a java profiler (YourKit) and I can see my running ServerSocket listen thread and it never sleeps and it's always running.

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

Basically, the profiler is misleading you.

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

I assume your code looks like this:

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

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!
}

This will not consume significant CPU ... unless you have done something pathological, like calling ServerSocket.setSoTimeout(int) with a small timeout.

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

#4


0  

Let the core sleep a little. In your Runnable method, add something like

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

Thread.sleep(250); // milliseconds 

in every loop.

在每个循环中。

That should significantly reduce CPU usage

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

Edit: bad idea, see comments, sorry, my fault

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


And: don't use while(true). it's awful design, as the semantics suggest that eventually true will not be true anymore. Usually you will want to query some volatile or atomic variable from the main thread

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

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);

}

That way the main thread has a way to stop the listener thread.

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

#1


8  

If you mean something like this:

如果你的意思是这样的:

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

then, no, the call to accept() does not "take an entire core." It's a blocking call that will allow the CPU to be scheduled for another thread until a client actually connects. Once the call to accept() returns, the current thread will be scheduled to run and will consume CPU until it blocks on accept() in the next iteration of the loop.

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

To avoid the listen backlog of other clients growing too large, another thread usually handles interaction with the newly-accepted Socket, leaving one thread to focus on accepting new clients. The socket handling thread might handle many sockets, using NIO, or it might be dedicated to a single socket, which is much simpler to code but won't scale well past many hundreds of simultaneous connections.

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

#2


5  

You might want to take a look at the Java 1.4 nio libraries and in particular ServerSocketChannel. I use this very successfully to implement an efficient server, the key bits of code are:

您可能希望查看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();

And the listener is just a loop that runs:

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

selector.select(1000); // listen for one second max
Set<SelectionKey> keys = selector.selectedKeys();

if (keys.size()>0) {
    handleKeys(keys);
}

#3


3  

I used a java profiler (YourKit) and I can see my running ServerSocket listen thread and it never sleeps and it's always running.

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

Basically, the profiler is misleading you.

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

I assume your code looks like this:

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

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!
}

This will not consume significant CPU ... unless you have done something pathological, like calling ServerSocket.setSoTimeout(int) with a small timeout.

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

#4


0  

Let the core sleep a little. In your Runnable method, add something like

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

Thread.sleep(250); // milliseconds 

in every loop.

在每个循环中。

That should significantly reduce CPU usage

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

Edit: bad idea, see comments, sorry, my fault

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


And: don't use while(true). it's awful design, as the semantics suggest that eventually true will not be true anymore. Usually you will want to query some volatile or atomic variable from the main thread

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

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);

}

That way the main thread has a way to stop the listener thread.

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