Before we continue to dive into the concepts and design of AIO (asynchronous IO), we need to make the differences between NIO (non-blocking IO) and AIO, from the kernel perspective.
Difference Between Blocking and Synchronous
We have already heard the phrase like Blocking IO
and Synchronous IO
, but what the differences here?
In order to understand it, we need to see that when we do a IO operation, it generally has two phases:
- Our user process submit the IO operation to OS kernel, i.e. call a
System Call
of OS: If our user process is blocked when submitting IO job to OS kernel, we call it asBlocking IO
. If it is not blocked, on the other hand, we call itNon-blocking IO
. - The OS kernel coordinate many kernel process, like
Disk Driver
&File System
, to do the real IO operation: If our process still waiting when OS doing real IO operation, we call itSynchronous IO
. Otherwise, it is calledAsynchronous IO
.
So we can see how Java IO model evolved:
Blocking IO: stream & reader
=>
Blocking Synchronous multiplex IO: selector & channel & buffer
# Even the `select` has time out mechanism, it is still blokcing.
# So, the term `NIO` may better be seen as `New IO`, but not Non-blocking IO
=>
Non-Blocking Aynchronous IO: aynchronous channel & callback
And here is a question with illustration describes the differences.
Async IO
In Async IO
, we still have Channel
and Buffer
, but the AsynchronousChannel
has different interfaces comparing with normal Channel
. It can receive a CompletionHandler
, which is the callback method when IO operation is done.
<A> void read(ByteBuffer dst,
A attachment,
CompletionHandler<Integer,? super A> handler);
<A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler);
Also, Java provides similar interfaces to make it Synchronous
:
Future<Integer> read(ByteBuffer dst);
CompletionHandler
and Callback
This interface is very readable, and the attachment
is Buffer
in most of times. When the IO operation is done, the completed
method will be called and failed
will be invoked when some exception happens.
public interface CompletionHandler<V,A> {
void completed(V result, A attachment);
void failed(Throwable exc, A attachment);
}
Thread Pools
As the CompletionHandler
is called in asynchronous way, we need to find a thread to run the code in it. If we use the thread submitted the IO job, this thread may be interrupted frequently and normal process maybe influenced. So, Java decided to add an thread pools to do it in background threads (if we doesn’t provide one, Java will provide ).
What should be noticed is two points related about the usage of thread pool:
- The completion handler should never be blocking indefinitely, otherwise worker in thread pool will be drained. In other word, the task in completion handler should be fast and short;
- The thread pool must support unbounded queueing.
For more information, refer to openjdk: notes on aio implementation.
Ref
Written with StackEdit.
评论
发表评论