Non Blocking with Traditional Java IO - On the Use of InputStream.available() and Thread.sleep()Jun 8, 2006 · 2 minute read · Comments
Some time ago I did quite a lot of IO in Java and I yet did not see this way of reading a InputStream from a Socket:
This comes from a piece of code from an example of JSch , a good ssh client in java. A work collegue had the bad idea to remove the Thread.sleep call and was struggling with why it would randomly work.The way I would have done it is the following:
This has the advantage of being more readable and having less secret spices in it. In the first code, the call to available() is non blocking, meaning that without the Thread.sleep(), there will never be the time for the socket buffer to fill up. But is the first code more efficient or the second code?
I did a search on google to understand the interest of the first code. The only advantages I found in the first code are the possibility to interrupt the thread running the code and a finer grained control on timeouts.
There is a lengthy explanation by Doug Lea in his book “Concurrent Programming in Java”. This book usually provides excellent explanations, and is a must read for anybody doing concurrent programming. But this time, about this subject, I did not find him that clear.
There is a more simple explanation in a course from San Diego State University (see last example)
A read() on an inputstream or reader blocks. Once a thread calls read() it will not respond to interrupt() (or much else) until the read is completed. This is a problem when a read could take a long time: reading from a socket or the keyboard. If the input is not forth coming, the read() could block forever.
As usual, you should not rely on all what you read on the web, as this page (SCJP Questions & Answers) testifies:
Q. When will a Thread I/O blocked?A:When a thread executes a read() call on an InputStream, if no byte is available. The calling Thread blocks, in other words, stops executing until a byte is available or the Thread is interrupted.
Still I am wondering if the second code would not just go into IOException (socket timeout), on timeout (adjustable with Socket.setTimeout ) and release the Thread then. Do you have an idea when the first code could be better?