A0A
A0A

Reputation: 118

Non-blocking Async IO in Java

Is there any way to do asynchronous IO in Java without blocking any threads (including background threads)? Coming from C#, my understanding of async IO is that it when you call

await ReadAsync()

The calling thread (part of a threadpool) steps into the ReadAsync function, at some point calls an asynchronous read function from the OS kernel, and then adds itself back to the threadpool to pick up other Tasks. Once the read is completed, the threadpool is notified and another thread picks up the rest of the Task.

In Java, on the other hand, the documentation and this answer seem to suggest that asynchronous IO functions are simply called by a background thread that then blocks. This seems less performant. Is there any way to achieve true, non-blocking IO in Java?

Upvotes: 1

Views: 1924

Answers (2)

ikorennoy
ikorennoy

Reputation: 230

Until some time ago there were problems with asynchronous file I/O on Linux. There was an aio interface, but it was only asynchronous for O_DIRECT, which is quite inconvenient for standard use cases. So the standard JDK implementation of AsynchronousFileChannel for Linux internally uses thread pooling and simple blocking I/O which is not really asynchronous I/O.

Things have changed a bit since Linux introduced the io_uring interface. It is now possible to use real non-blocking file I/O not just for O_DIRECT but for buffered I/O too. And a lot more, to reduce overhead of syscall and increase performance. Read more about io_uring.

At the moment there is no built-in support for io_uring in Java. There have been rumors that support may appear for better project Loom support, but that's just a rumors.

There are third party libraries that add asynchronous file I/O support via io_uring for Java - jasyncfio.

Upvotes: 2

Miguel Gamboa
Miguel Gamboa

Reputation: 9353

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.

Upvotes: 3

Related Questions