Java non-blocking I/O

Java SUCKS! Platform independence doesn’t come with a high price. The last two days I have been trying to do asynchronous non-blocking I/O and got really frustrated. Moreover, I come to think that what I really wanted is simply not possible.

Correction – Java sucks LESS ;-) It’s not so well documented though…

I have a fully functional non-blocking IO for Java 1.4. It is multithreaded and it works great.

What I tried first:

SOLUTION1

InputStream in = System.in;

while(wantToContinue) {

while (in.available() == 0) {
try {Thread.sleep(sometime); }
catch(InterrputerException ioe) {};
}

int bytesRead = in.read(buffer);

}

PROBLEM1
available() doesn’t report any data on end of file (which is reported by non-blocking read() returning -1), so there’s no way to detect this state.

SOLUTION2
Ok, what if we do the blocking I/O in a separate thread and simulate non-blocking I/O to the main thead (a simple producer-consumer programming exercise).

PROBLEM2
Once, a thread is stuck in a blocking read(), there’s NO WAY to terminate it. Closing the stream, interrupting or even terminating the thread has no effect whatsoever.

(PARTIAL) SOLUTION 2
The same as solution2, but assuming that we want to terminate the thread at the end of application, we can simply cat System.exit() in a finally{} statement.

Ugly like hell, but for our limited purposes, it works.

CONCLUSION
Java is a nice programming language, but it’s of limited use for writing a simple Unix-like tools processing streams asynchronously (pipes, reading from stdin, etc.). java.nio (NEW I/O) doesn’t help here at all.

IMPROVED AND WORKING SOLUTION:
Use Channels, but unstead of converting System.in to Channel, we use
FileChannel fc = new FileInputStream(FileDescriptor.in).getChannel();
ByteBuffer b = ByteBuffer.wrap(tmpBuffer);

Now synchronous calls to FileChannes CAN be interrupted. BTW: it’s still not selectable though, which means we have to use another (ternimable this time) thread to do non-blocking ops.

Leave a Reply