Question

I'm writing multithreaded socket server. I use nio's ServerSocketChannel for accepting connections. Then Ii'm reading and writing (in separate threads) to socketChannel using bufferedreader and print writer. The problem is that PrintWriter locks and waits on flush() command. It blocks thread until the BufferedReader receive data.

Was it helpful?

Solution

That indicates that the receiver is slow reading. That's how blocking I/O works. If you want non-blocking I/O you're already part of the way there, as you are already using NIO. Although I really don't see the point of using NIO in blocking mode at all.

OTHER TIPS

As @EJP says, that is basically the way that blocking IO works. Indeed, this problem is inherent in any architecture where you have a producer and a consumer. If the producer produces stuff (in this case lines of text output) faster than the consumer can consume it, then the producer eventually has to block.


How can you solve this? First some general stuff.

If the producer produces stuff faster than the consumer consumes it in long term, you are between a rock and a hard place. You must either reduce the producer's rate of production, speed up the consumer's rate of consumption, or reduce the overheads in the pipeline to the same effect. Nothing else works.

If rate mismatch is only temporary, you can "paper over the cracks" by adding some extra buffering to the pipeline. If the connection between has some buffering capability, you may be able to increase it. Alternatively, you could add extra buffering at the producer or consumer end.


Here are some things that might help in your particular case.

  • Reduce the amount of stuff you are writing in the producer threads.

  • Do less work in the consumer threads, or profile / tune them to do the work faster.

  • Don't use a socket to communicate between two threads in the same JVM. If you can arrange it, use a Java PipeInputStream / PipeOutputStream pair, or roll your own equivalent. (If you use a socket, reading and writing involves system calls, copying data into and out of kernel buffers and so on.)

  • In the case where communications has to go outside of the JVM, make sure that you use Buffered* wrappers for the underlying streams to reduce the number of syscalls made while reading / writing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top