One, look at the picture
A lot of IO data on the Internet, for beginners, the more look more dizzy. According to their own understanding, summed up the comparison of bio, NIO, AIO.
BIO: The thread initiates an IO request, and the thread blocks until the operation completes, regardless of whether the kernel is ready for IO operation. The following figure:
NIO (reactor model): Thread initiates IO request, returns immediately; After the kernel is ready for IO operation, the thread begins to block until the operation completes by calling the registered callback function to notify the threads to do IO operations. The following figure:
AIO (Proactor model): Thread initiates IO request, returns immediately; memory completes IO operation after preparation, do IO operation, until the operation completes or fails, by calling the registered callback function to notify the thread do IO operation or failure. The following figure:
Second, detailed
1, BIO
Before the JDK1.4 came out, when we set up a network connection with the Bio mode, we need to start a serversocket on the server, and then start the socket on the client to communicate to the server, by default, the server needs to set up a heap of threads to wait for the request, and the client sends the request, first consults the server Whether the thread is appropriate, if not, it will wait or be rejected, and if so, the client will wait until the request is finished before continuing.
2. NIO
NiO itself is based on event-driven thinking, primarily to solve the big concurrency problem of bio: In network applications that use synchronous I/O, you must use multithreading if you want to handle multiple client requests simultaneously, or if the client wants to communicate with multiple servers at the same time. In other words, each client request is assigned to a thread to handle separately. While this can meet our requirements, it also poses another problem. Because each thread is created, it allocates a certain amount of memory (also known as working memory) to the thread, and the operating system itself limits the total number of threads. If there are too many requests from the client, the server-side program may be overwhelmed to deny the client's request, and even the servers may become paralyzed.
NIO is based on reactor, and when the socket has a stream readable or writable socket, the operating system processes the corresponding notification reference program, and then reads the stream to the buffer or writes to the operating system. In other words, this time, is not a connection will be a processing thread, but a valid request, corresponding to a thread, when the connection has no data, there is no worker thread to deal with.
One of the more important differences between bio and NiO is that when we use the bio, we tend to introduce multiple threads, each connecting a single thread, while NIO uses a single thread or uses only a small number of threads, and each connection has a common one.
The most important place for NIO is that when a connection is created, it does not need to correspond to a thread, this connection will be registered on the multiplexer, so all the connections need only one thread can be done, when the multiplexer in this thread polling, found the connection on the request to open a thread to handle, That is, a request for a threading pattern.
In the process of NIO, when a request comes in, open the thread to process, may wait for the backend application resources (JDBC connection, etc.), in fact, this thread is blocked, when the concurrent up, there will be the same problem with the bio.
The http/1.1 appears with an HTTP long connection so that, in addition to timing out and specifying the HTTP header for a particular shutdown, the link is always open, so that it can evolve further in NIO processing, and a resource pool or queue can be implemented in the backend resources, and when requested, The open thread sends the request and request data to the back-end resource pool or the queue to return. And in the overall place to maintain the site (which the connection of which request, etc.), so that the previous thread can still accept other requests, the application of the latter end of the processing only need to execute the queue within the can, This allows the request processing and the backend application to be asynchronous. When the backend is processed, the scene is generated to the global place, and the response is realized, and the asynchronous processing is achieved.
3, AIO
Unlike NIO, the read or write method of the API must be invoked directly when reading and writing. Both of these methods are asynchronous, and for read operations, when there is a stream to read, the operating system transmits the readable buffer to the Read method and notifies the application; for write operations, the operating system proactively notifies the application when the operating system writes the stream passed by the write method to completion. It can be understood that the Read/write method is asynchronous and will invoke the callback function when it is finished. In JDK1.7, this part of the content is called nio.2, which adds the following four asynchronous channels, mainly under the Java.nio.channels package: Asynchronoussocketchannel Asynchronousserversocketchannel Asynchronousfilechannel Asynchronousdatagramchannel
The Read/write method, which returns an object with a callback function, calls the callback function directly when the read/write operation is completed.
Bio is a connection to a thread.
NIO is a request for a thread.
AIO is a valid request for a thread.
Let's start with an example to understand the concept of bank withdrawals as an example: Sync: Personally take the bank card to the bank to withdraw money (when using synchronous io, Java handles IO read and write itself); asynchronous: Entrust a little brother to take a bank card to the bank for money and then to you (when using asynchronous IO, Java delegates io Read and write to OS processing, The data buffer address and size need to be passed to the OS (bank card and password). OS needs to support asynchronous IO operations APIs; blocking: ATM queuing for withdrawals, you can only wait (when using blocking IO, Java calls are blocked until read-write is completed); Non-blocking: counter withdraw, take a number, And then sit in the chair and do other things, the equal sign broadcast will inform you to handle, not to the number you cannot go, you may unceasingly ask the lobby manager to have not arrived, the lobby manager if said that does not arrive you cannot go (uses non-blocking io, if cannot read and write Java call will return immediately, When the IO event distributor notifies the reader that it can read and write, continue to cycle until read and write.
Java support for bio, NIO, and AIO:
Java BIO: Synchronization and blocking, the server implementation mode for a connection to a thread, that is, when the client has a connection request, the server needs to start a thread to process, if this connection does not do anything will cause unnecessary threading overhead, of course, can be improved through the thread pool mechanism.
Java NIO: Synchronous non-blocking, server implementation mode for a request of a thread, that is, the client sent a connection request will be registered to the multiplexer, multiplexer polling to connect with I/O requests before starting a thread to process.
Java AIO (nio.2): Asynchronous non-blocking, server implementation mode for a valid request of a thread, the client's I/O requests are first completed by the OS and then notify the server application to start the thread processing,
BIO, NIO, AIO application Scenario analysis:
The bio method is suitable for a small number of connections and a fixed architecture, this approach to the server resource requirements are relatively high, concurrent limited to applications, JDK1.4 before the only choice, but the program intuitive simple and easy to understand.
NiO method suitable for the number of connections and relatively short (light operation) of the architecture, such as chat server, concurrency limited to applications, programming is more complex, JDK1.4 began to support.
AIO mode for the number of connections and relatively long (heavy operation) of the architecture, such as photo albums Server, fully invoke the OS to participate in concurrent operations, programming more complex, JDK7 began to support.
In addition, I/O belongs to the underlying operation, requires operating system support, concurrency also requires the support of the operating system, so the performance of different operating system differences will be more obvious.
In High-performance I/O design, there are two well-known patterns reactor and Proactor modes, where the reactor mode is used to synchronize I/O, while Proactor is applied to asynchronous I/O operations.
Before you compare these two patterns, we first understand a few concepts, what is blocking and non-blocking, what is synchronous and asynchronous, synchronous and asynchronous are for application and kernel interaction, synchronization refers to the user process triggering IO operations and waiting or polling to see if the IO operation is ready, Asynchronous means that the user process triggers the IO operation and then starts to do its own thing, and when the IO operation has been completed, it will be notified of IO completion. And blocking and non-blocking are aimed at the process when accessing the data, depending on how the IO operation is ready, it is a way to read or write a function that reads or writes to the function, and the read or write functions will wait instead of blocking, and the read or write function immediately returns a status value.
Generally speaking I/O model can be divided into: synchronous blocking, synchronous non-blocking, asynchronous blocking, asynchronous non-blocking IO
Synchronous blocking IO: In this way, the user process must wait for the IO operation to complete after an IO operation is initiated, and the user process will not run until the IO operation is actually completed. The Java traditional IO model belongs in this way.
Synchronous non-blocking IO: In this way, the user process initiates an IO operation to return to doing other things, but the user process needs to ask the IO operation to be ready from time to time, which requires the user process to constantly ask, thus introducing unnecessary CPU waste. The current Java NiO belongs to synchronous non-blocking io.
Asynchronous blocking IO: This means that after the application initiates an IO operation, do not wait for kernel IO operations to complete, and so the kernel completes the IO operation will notify the application, this is actually synchronous and asynchronous the most critical difference, synchronization must wait or actively ask IO is completed, then why is it blocked? Because this is done by a select system call, and the Select function itself is implemented in a blocking way, the advantage of the Select function is that it can listen for multiple file handles at the same time, increasing the concurrency of the system.
Asynchronous non-blocking IO: In this mode, the user process only needs to initiate an IO operation and then return immediately, and when the IO operation is actually completed, the application will be notified of the IO operation, at which point the user process needs only to process the data, without the need for actual IO read and write operations, Because the true IO read or write operation has been completed by the kernel.