Using Executor instead of new Thread for Server socket clients

Go To StackoverFlow.com

1

I'm currently writing a server which multiple clients will connect to. The communication protocol is basically that the server sends a task to the clients and the clients respond when the task is performed. The clients stay connected to the server and should never disconnect.

Currently I'm starting a new Thread to handle each client. In spirit my current solution is like this: (source from Java Concurrency in practice)

public class ThreadPerTaskWebServer {
    public static void main(String[] args) throws IOException {
        ServerSocket socket = new ServerSocket(80);
        while (true) {
            final Socket connection = socket.accept();
            Runnable task = new Runnable() {
                public void run() {
                    handleRequest(connection);
                }
            };
            new Thread(task).start();
        }
    }

    private static void handleRequest(Socket connection) {
        // request-handling logic here
    }
}

But I would like to use Executors since they seem more stable and scale better. So in order for the server to be able to send messages to the clients I would need to keep track of the clients separately from the Executor running them. So if I where to place the clients in an CopyOnWriteArrayList clients and then have something like this in the Server class:

Socket clientSocket = serverSocket.accept();
// The runnable that takes care of a client 
ClientHandler c = new ClientHandler(clientSocket, this);
// Start executing the ClientHandler
exec.execute(c);
// Add clients to CopyOnWriteArrayList
clients.add(c);

This would allow me to iterate over the CopyOnWriteArrayList in order to send commands to all the clients and also remove disconnected ones. Would this the an robust solution? What would happen with the Executor if a runnable for some reason would propagate an exception to it?

2012-04-05 19:18
by Teletha
You are mixing up clients and servers. In your case clients are servers and vise versa - ahanin 2012-04-05 19:21
@ahanin I agree it's not totaly clear but I think this is the most correct description. Since the clients connect to the server (and it has the ServerSocket) it becomes per definition the server : - Teletha 2012-04-05 19:38
I'm not confused, I totally understood what was the intent, I just wanted to point that @Teletha is mixing up concepts. In the described case clients are kind of worker agents that serve "server's" request for task execution - ahanin 2012-04-05 19:52
You're right @ahanin. I skimmed over the first paragraph. Sorry - Gray 2012-04-05 20:17


1

Would this the an robust solution?

Yes, I think so. You need to make sure you either allocate the right number of threads in your fixed size pool or use a dynamic pool.

What would happen with the Executor if a runnable for some reason would propagate an exception to it?

If your code throws a RuntimeException then the executor pool thread executing the code will stop but the pool thread count will be decremented and another thread created if the service has not already been shutdown. So the thread pool will continue to operate appropriately.

This would allow me to iterate over the CopyOnWriteArrayList in order to send commands to all the clients and also remove disconnected ones

You would not need to remove the disconnected ones unless you were saving a reference to them of course. Otherwise I can't really comment on this requirement.

2012-04-05 19:25
by Gray


1

If you choose the thread per connection approch and you don't want use NIO api, I believe this is a good solution. But remember that if your pool size is smaller than the number of concurrent requests you have clients pending until previous requests end.

About what happens if you got an exception in your task: the thread terminates but executor will create other threads.

2012-04-05 19:31
by dash1e
Ads