views:

169

answers:

4

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

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.

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?

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.

Thanks everyone

A: 

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

Thread.sleep(250); // milliseconds 

in every loop.

That should significantly reduce CPU usage

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

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.

seanizer
I'm not sure this is a great idea, as it will rate limit your connections.
spong
yup, I misread the question. I thought it was just a thread that waited for some service to start up, but for a Socket listener that actually listens to user requests, this is bad advice.
seanizer
hi , in what context you meant "true will not be true anymore" ?
Bragboy
I mean: what you are saying is 'while true is true, keep going'. However, if you have a break or throw or return statement anywhere inside the loop, you are thereby suggesting that true is not true anymore and that is semantically awkward although technically ok.
seanizer
@seanizer - IMO best approach is to put the `while (true)` *inside* the try block with the catch for `InterruptedException`.
Stephen C
+3  A: 

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.

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.

erickson
+1  A: 

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:

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);
}
mikera
I was looking into socket Channels, thanks for posting this!
Submerged
+1  A: 

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

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.

Stephen C