I am currently working on a Java Servlet application (using blackdown's JDK with green threads and Apache JServ) which does extensive file I/O and database connections. Non-blocking I/O can really be a pain when you have multiple users doing expensive database queries.
Solution:
Java provides the facilities to implement your own non-blocking I/O regardless of which threads implementation you are running.
Assuming you have control over all file operations, you can write an input stream filter which overrides the read() methods of java.io.InputStream to something like this :
public int read() throws IOException { int i; for (i=0 ; iTRIES ; i++) if (in.available() != 0) break; else Thread.yield(); return in.read(); }
The only drawback of this method (and the reason behind the for loop) is that on EOF, in.available() returns 0 although there is still the EOF byte (-1) yet to be read.
I found it to be fairly efficient to implement caching on top of this (and easy to implement too in Java).
In order to add this facility to Socket operations outside of your control (such as JDBC drivers), you can subclass java.io.SocketImpl to return your non-blocking input stream class from getInputStream() and use Socket.setSocketImplFactory() to force new sockets to use your input stream. (However this won't work if the JDBC driver provides its own SocketImplFactory).
Oh yeah - the socket thing also won't work for anything that uses native methods for I/O.
I am currently working on a Java Servlet application (using blackdown's JDK with green threads and Apache JServ) which does extensive file I/O and database connections. Non-blocking I/O can really be a pain when you have multiple users doing expensive database queries.
Solution:
Java provides the facilities to implement your own non-blocking I/O regardless of which threads implementation you are running.
Assuming you have control over all file operations, you can write an input stream filter which overrides the read() methods of java.io.InputStream to something like this :
public int read() throws IOException
{
int i;
for (i=0 ; iTRIES ; i++)
if (in.available() != 0)
break;
else
Thread.yield();
return in.read();
}
The only drawback of this method (and the reason behind the for loop) is that on EOF, in.available() returns 0 although there is still the EOF byte (-1) yet to be read.
I found it to be fairly efficient to implement caching on top of this (and easy to implement too in Java).
In order to add this facility to Socket operations outside of your control (such as JDBC drivers), you can subclass java.io.SocketImpl to return your non-blocking input stream class from getInputStream() and use Socket.setSocketImplFactory() to force new sockets to use your input stream. (However this won't work if the JDBC driver provides its own SocketImplFactory).