Many articles talk about BIO, NIO, AIO and just throw out a bunch of definitions and some vivid examples. That seems pretty straightforward. But it does not show the most basic essential principle, and it is difficult to understand the difference between the three without starting from the principle of IO. So this article starts with an analysis of how Java performs IO operations.

IO principles in Java

First of all, THE IO in Java is dependent on the operating system kernel, and the IO reading and writing in our program actually calls the two system calls of read and write in the operating system kernel.

How does the kernel interact with IO?

  1. The network adapter receives network data from the network cable and writes the network data to the memory.
  2. When the nic data to the memory, the NIC to the CPU issued an interrupt signal, the operating system will be able to know the arrival of new data, and then through the nic interrupt program to deal with the data.
  3. Writes network data in memory to the receive buffer of the corresponding socket.
  4. When the data for the receive buffer is written, the application begins to process the data.

The following is a simple example of socket code abstracted to Java:

Public class SocketServer {public static void main(String[] args) throws Exception {// Monitor the specified port int port = 8080; ServerSocket server = new ServerSocket(port); Socket Socket = server.accept(); InputStream InputStream = socket.getinputStream (); byte[] bytes = new byte[1024]; int len;while((len = inputStream.read(bytes)) ! String message = new String(bytes, 0, len,"UTF-8"); } // socket, server, stream close operation, omit not table}}Copy the code

You can see that this process is very similar to the network IO of the underlying kernel, in that accept() waits for requests from the network to arrive and then the Bytes [] array acts as a buffer waiting for data to fill up. The difference between BIO, NIO, and AIO is whether these operations are synchronous or asynchronous, blocking or non-blocking.

So we introduce the concepts of synchronous asynchrony, blocking and non-blocking.

Synchronous and asynchronous

Synchronous and asynchronous refers to whether each method in an execution process must depend on the completion of the previous method before execution can continue. Suppose our execution flow is: method 1 and method 2 in order.

Synchronization refers to the fact that once the call has started, the caller must wait until the method call returns before continuing with the subsequent behavior. Method two must wait until method one has finished executing.

Asynchronous means that the call returns immediately and the caller does not have to wait for the code execution within the method to finish before continuing with the subsequent behavior. Callbacks may occur after the code in a specific method is handed off to another thread. That is, when method 1 is executed, it is directly handed over to another thread, not the main thread, so it does not block the main thread, so method 2 does not have to wait for method 1 to complete.

Synchronous and asynchronous are concerned with whether the method is executed by the main thread, which waits for the method to complete, or another thread, which can execute the following code without waiting for the method to return immediately.

Synchronization and asynchrony achieve efficiency differences through coordination between multiple threads.

Why asynchrony? The author thinks that the essence of asynchrony is to solve the blocking of the main thread, so there are many discussions on the Internet about the four combinations of synchronous asynchrony and blocking non-blocking, one of which has asynchronous blocking. What if asynchrony is also blocking? So why do asynchronous operations specifically?

Blocking and non-blocking

Blocking and non-blocking refers to whether a single thread does nothing in place when it encounters a synchronous wait.

Blocking refers to waiting in place for a synchronous method to complete processing after a synchronous wait is encountered.

Non-blocking means that when a synchronous wait is encountered, instead of waiting in place, other operations are performed first, and the time is cut off to observe whether the synchronous method is complete.

Blocking versus non-blocking concerns whether the thread is waiting in place.

The authors argue that blocking and non-blocking can only be combined with synchronization. Asynchrony is naturally non-blocking, and this non-blocking is for the main thread. (Some people might think that blocking operations in asynchronous methods are asynchronous blocking, but consider that blocking operations are placed in asynchronous methods because they are blocking. Do not block the main thread.)

example

Haidilao is delicious, but there are always queues. Let’s take this example from life.

  • Customer A went to haidilao and sat there waiting for an hour before eating hot pot. (BIO)
  • B customer to eat haidilao, he a look to wait for a long time, so go shopping mall, each shopping for a while to run back to see if there is no row to him. So he ended up both shopping and eating Shanghai dicilao. (NIO)
  • Customer C went to haidilao. As he was a senior member, the store manager said, “You can go to the mall and enjoy yourself. I will call you as soon as there is a seat available.” Therefore, customer C did not have to sit and wait, nor did he have to come back every few moments to see if he had waited. Finally, he also ate Haidilao (AIO).

Which is more efficient? Is it easy to see?

BIO

As a traditional IO model before JDK1.4, BIO is Blocking synchronously. After the thread initiates an IO request, it blocks the IO until the buffer data is ready before proceeding to the next step. Network communication is a request for a response, although it simplifies the upper application development, but there is a huge bottleneck in performance and reliability, just imagine if each request needs to create a new thread to deal with, so in high concurrency scenarios, machine resources will soon be exhausted.

NIO

NIO also called non-blocking IO is a synchronous non-blocking IO model. The thread makes an I/O request and immediately returns (non-blocking I/O). Synchronization means that the user thread must wait for the IO buffer to be ready, rather than blocking. The user thread can do something else first, but polling periodically to check whether the IO buffer is ready. NIO in Java stands for New IO. NIO plus IO multiplexing. Whereas normal NIO is threads polling to see if an IO buffer is ready, new IO in Java is threads polling to see which IO buffers are ready, an idea of I/O multiplexing. In the IO multiplexing model, the task of checking the I/O data readiness is assigned to the system-level SELECT or Epoll model, which is monitored by the system to reduce the burden of user threads.

NIO is mainly the integration of buffer, channel and selector technologies. Data is obtained through zero-copy buffer, and each client registers with selector (multiplexer) through channel. The server constantly polls the channel for information about the client. A channel has connect, Accept, read, and write status identifiers. Follow the identity for subsequent operations. So a server can receive an infinite number of channels. You don’t need to start a new thread. Greatly improved performance.

AIO

AIO is truly an asynchronous non-blocking IO model. In the NIO implementation above, the user thread is required to poll periodically to check whether the IO buffer data is ready, occupying the thread resources of the application. In fact, polling is still blocking, not really freeing the current thread, because it still needs to query which IO is ready. The real ideal of asynchronous non-blocking IO would be to let the kernel do it, and the user thread would simply tell the kernel to either notify me when the buffer is ready or execute the callback I’ve given you.

AIO can achieve real asynchronous operations, but the implementation is relatively complicated. There are very few operating systems that support pure asynchronous IO. At present, Windows is implemented by IOCP technology, while on Linux, the bottom layer is implemented by epoll.

The author understands summary personally, if have error request netizen comment to correct.

My personal blog, vc2x.com