I\'m writing a Java server which uses plain sockets to accept connections from clients. I\'m using the fairly simple model where each connection has its own thread reading f
I'd suggest it depends more on exactly what else the server is doing when it processes the messages. If it's relatively lightweight then your machines spec should EASILY cope with merely handling the connections of thousands of such processes. Tens of thousands is another question perhaps, but you only need two machines on the same network to actually empirically test it and get a definite answer.
It is possible this will scale to thousands of clients. But how many thousands is the next question.
A common alternative is to use Selectors and non-blocking I/O found in the java.nio package.
Eventually you get into the question of whether it's useful to set up your server in a clustered configuration, balancing the load over multiple physical machines.
Try Netty.
the "one thread per request" model is the way most Java app servers are written. Your implementation can scale as well as they do.
Threads aren't as expensive as they used to be, so an "ordinary" IO implementation can be ok to a point. However if you are looking at scaling to thousands or beyond it is probably worth investigating something more sophisticated.
The java.nio package solves this by providing socket multiplexing/non-blocking IO which allows you bind several connections to one Selector. However this solution is much harder to get right than the simple blocking approach because of the multithreading and non-blocking aspect.
If you wish to pursue something beyond the simple IO then I would suggest looking at one of the good quality network abstraction libraries out there. From personal experience I can recommend Netty which does most of the fiddly NIO handling for you. It does however have a bit of a learning curve but once you get used to the event based approach it is very powerful.
I think a better approach is to not handle threads yourself. Create a pool (ThreadExecutor or some other stuff) and simple dispatch work to your pool.
Of course, I think asynchronous I/O will make it better and faster, but will help you with socket and networking problems. Only. When your threads block because of I/O, the JVM will put it to sleep and change for another thread until the blocking I/O return. But this will block only the thread. Your processor will continue to run and start to proccess other thread. So, minus the time to create a thread, the way you use I/O not affect not much your model. If you do not create threads (using a pool) your problem is solved.
This will scale well for up to hundreds of connections, not to thousands. One issue is that a Java thread takes quite a bit of stack as well (e.g. 256K), and the OS will have problems scheduling all your threads.
Look at Java NIO or framworks that will help you get started doing complex stuff more easily (e.g. Apache Mina)