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.