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