I have implemented a server in Java, upon receiving data from some client it simply forwards the data to all other clients (including the sender). I'm happy with my OO-design, I wrap all sockets in classes that provide 'callbacks'. These are called when some data are ready (or when the socket closes) -- using this design I could easily implement a simple TLV protocol to atomically send packets: the callback is not called until a full packet is received.
Now, I use the java.io
package blocking I/O calls to the socket streams (and make them appear 'asynchronous' through those callbacks). So I use threads inside my socket wrapper classes: when a socket is opened, that function returns a Runnable
implementation that, when run, will do the blocking calls to the InputStream
, buffer data and eventually call the callback.
=> In a client application, I simply launch this Runnable
in a Thread
instance, because it's just one thread.
=> In my server, I submit all Runnable
implementations I get upon creating new sockets (i. e. when accepting new clients) into a ThreadPoolExecutor
. (FYI: the callbacks of the sockets simply put
the received packets in a BlockingQueue
. A single, separate (non-pooled) "dispatcher" Thread
instance constantly take
s the packets from this queue and writes them to all sockets currently connected to the server.)
QUESTION: This all works great, however I'm unsure about my use of the ThreadPoolExecutor
, because the Runnable
instances submitted are almost always blocking. Will the ThreadPoolExecutor
react to this? Or will the pooled threads simply block? Because, if all pooled threads are all blocking while executing their Runnable
and next, a new Runnable
is submitted, then what? Suspend the new Runnable
? That's not good, because then the newly connected client will have zero responsiveness until some older client disconnects. If by contrast the thread pool chooses to spawn a new thread to handle the Runnable
, then I actually get a thread-per-client scenario.
I want the thread pool to 'preempt' the blocking threads and use them to handle other sockets, like an operating system that suspends I/O bound processes and doesn't schedule them again until their I/O is complete. Is that at all possible, or will I have to rewrite everything using nio
in order to do this? (if nio
is required, could you point out where I should start reading?)
Thanks in advance!