Asynchronous Io in Java

non-blocking IO vs async IO and implementation in Java

So what is actually "non-blocking async IO"?

To answer that, you must first understand that there's no such thing as blocking async I/O. The very concept of asynchronism dictates that there's no waiting, no blocking, no delay. When you see non-blocking asynchronous I/O, the non-blocking bit only serves to further qualify the async adjective in that term. So effectively, non-blocking async I/O might be a bit of a redundancy.

There are mainly two kinds of I/O. Synchronous and Asynchronous. Synchronous blocks the current thread of execution until processing is complete, while Asynchronous doesn't block the current thread of execution, rather passing control to the OS Kernel for further processing. The kernel then advises the async thread when the submitted task is complete


Asynchronous Channel Groups

The concept of Async Channels in java is backed by Asynchronous Channel Groups. An async channel group basically pools a number of channels for reuse. Consumers of the async api retrieve a channel from the group (the JVM creates one by default) and the channel automatically puts itself back into the group after it's completed its read/write operation. Ultimately, Async Channel Groups are backed by surprise, threadpools. Also, Asynchronous channels are threadsafe.

The size of the threadpool that backs an async channel group is configured by the following JVM property

java.nio.channels.DefaultThreadPool.initialSize

which, given an integer value will setup a threadpool of that size, to back the channel group. The channel group is created and maintained transparently to the developer otherwise.


And how all them can be implemented in Java

Well, I'm glad you asked. Here's an example of an AsynchronousSocketChannel (used to open a non-blocking client Socket to a listening server.) This sample is an excerpt from Apress Pro Java NIO.2, commented by me:

//Create an Asynchronous channel. No connection has actually been established yet
AsynchronousSocketChannel asynchronousSocketChannel = AsynchronousSocketChannel.open();

/**Connect to an actual server on the given port and address.
The operation returns a type of Future, the basis of the all
asynchronous operations in java. In this case, a Void is
returned because nothing is returned after a successful socket connection
*/
Void connect = asynchronousSocketChannel.connect(new InetSocketAddress("127.0.0.1", 5000)).get();

//Allocate data structures to use to communicate over the wire
ByteBuffer helloBuffer = ByteBuffer.wrap("Hello !".getBytes());

//Send the message

Future<Integer> successfullyWritten= asynchronousSocketChannel.write(helloBuffer);

//Do some stuff here. The point here is that asynchronousSocketChannel.write()
//returns almost immediately, not waiting to actually finish writing
//the hello to the channel before returning control to the currently executing thread

doSomethingElse();

//now you can come back and check if it was all written (or not)

System.out.println("Bytes written "+successfullyWritten.get());

EDIT: I should mention that support for Async NIO came in JDK 1.7

Non-blocking Async IO in Java

The AsynchronousFileChannel.open() returns instances of different implementations according to the running environment. On Windows it should return an instance of WindowsAsynchronousFileChannelImpl which uses I/O completion port and avoids blocking threads on IO operations. Threads of thread pool are only used to dispatch results and do not block, unless the end user programmer blocks that thread.

The RxIo is built on top of AFC and provides the AsyncFiles equivalent to the synchronous Files class but with an asynchronous API. Taking advantage of the continuation-passing style of CompletableFuture (equivalent to .net Task) you may read a file content without blocking:

AsyncFiles
.readAll(path)
.thenAccept(body -> /* invoked on completion */)
.exceptionally(excep -> /* invoked on error*/

You may run the unit tests of RxIo and place a breakpoint at open() and inspect the implementation of WindowsAsynchronousFileChannelImpl.

Asynchronous IO in Java?

Java's NIO package (as of Java6), provides support for non-blocking I/O only, via Selectors. Java7 is hopefully going to ship with NIO.2, which includes asynchronous I/O support. Today, your best bet is to make use of a framework. ARMistice mentioned Mina. Here are some others.

  1. Grizzly. This is the I/O core for Sun's GlassFish server. Grizzly provides a facility for doing asynchronous reads/writes (via a queue model). It supports TCP and UDP alike. I've used Grizzly in a couple of projects. There are things I like and dislike about the framework, but to detail this is really another topic. I will say that it's quite easy to get something up and running and Grizzly does a lot of the heavy lifting for you.
  2. Netty. This project comes from one of the original authors of the Mina project. I haven't used this one so I don't know about its support for asynchronous I/O. You should take a look.

Now, with regard to your question about threads, NIO Selectors do not use threads for non-blocking I/O. In JDK6 they use select() under Windows and the epoll facility on newer Linux kernels. For asynchronous I/O, threading details depend on the framework.

Java Non-Blocking and Asynchronous IO with NIO & NIO.2 (JSR203) - Reactor/Proactor Implementations

There are lots of factors involved in this one. I will try to summarize my findings as best as possible (aware of the fact that there is contention regarding the usefulness of reactor and proactor IO handling implementations).

Is proactor based IO handling possible
in Java in such a way that it is
advantageous to use for specific
scenarios.

Java 1.4 introduced non-blocking IO which is NOT the same as asynchronous IO. Java SE 7 introduces asynchronous IO with JSR203 making "true" proactor style IO handling implementations possible.

See AsyncrhonousSocketChannel, AsynchronousServerSocketChannel

and, if Java NIO does support proactor
based IO handling (either in Java 6 or
Java 7) is OS managed asynchronous IO
support (i.e. completion callbacks
from the OS) being utilized?

Reading through the JSR 203 specs, completion handlers using new asynchronous channels are definitely supported and it is reported that native OS features are being utilized but I have not ascertained to what extent yet. I may follow up on this after an analysis of the Java 7 source (unless someone beats me to it).

Furthermore, if the implementation is
purely in-VM are the performance
benefits so little that using
proactive event handling offers
nothing more than a different
(possibly simpler) way of constructing
concurrent network handling software.

I have not been able to find any performance comparisons regarding new Asynchronous IO features in Java 7. I'm sure they will become available in the near future.

As always, when presented with more than one way to tackle a problem the questions of which approach is better is almost always answered with "depends". Proactive event handling (using asynchronous completion handlers) is included with Java 7 and cannot simply exist without purpose. For certain applications, it will make sense to use such IO handling. Historically a common example given where proactor has good applicability is in a HTTP server where many short requests are issued frequently. For a deeper explanation give this a read (provided only to highlight the advantages of proactor so try to overlook the fact that example code is C++).

IMO it seems obvious that in many circumstances reactor/proactor complicate what would otherwise be a very simple design using a more traditional approach and in other more complex systems they offer a high degree of simplification and flexibility.

.
.
.

On a side note I highly recommend reading through the following presentation about NIO which offers performance comparison between NIO and the "traditional" approach. Though I would also advise caution regarding the results presented as the NIO implementation in the benchmark was based on the pre Java 1.4 NBIO NIO library and not the NIO implementation shipped in 1.4.

What is the primary use case for asynchronous I/O

If you are using Infiniband networks I would suggest looking at the Asynchronous IO.

Comparing Java 7 Async NIO with NIO.

However if you are using regular ethernet, it is just as likely to slower as faster. The coding is more complicated than using non-blocking IO which is more complicated than using blocking IO.

If latency is of utmost importance I suggest you look at using kernel by-pass network adapters like Solarflare. However if a 100 micro-second latency is acceptable to you, it is unlikely you need this.



Related Topics



Leave a reply



Submit