IO model overview
What is the IO model?
That is to say, it specifies the way to send and receive data, which greatly improves the communication performance. For example, the way of using UDP protocol communication is much more efficient than that of using TCP communication, but the use of the two also depends on different use scenarios. In some scenarios, the effect of using UDP will be better, while in others, TCP must be used. The same is true for IO models. Different IO models should be used in different scenarios. The same is true when looking for someone. It's not good-looking, rich, and suitable for yourself.
Noun introduction
-
Synchronization: I personally go to the bank to withdraw money with my bank card (when using synchronous IO, Java handles IO reading and writing by itself).
-
Asynchronous: entrust a younger brother to take the bank card to the bank to withdraw money, and then give it to you (when using asynchronous IO, Java entrusts IO reading and writing to the OS for processing, and needs to pass the data buffer address and size to the OS (bank card and password). The OS needs to support asynchronous IO operation API).
-
Blocking: ATM queues for withdrawal, and you can only wait (when blocking IO is used, Java calls will be blocked until reading and writing are completed).
-
Non blocking: withdraw money from the counter, take a number, and then sit on the chair to do other things. The equal sign broadcast will inform you to handle it. You can't go until the number arrives. You can keep asking the lobby manager whether it's in line, If the lobby manager says you can't go before it arrives (when using non blocking IO, if you can't read and write, the Java call will return immediately. When the IO event distributor will notify you to read and write, continue to read and write, and keep cycling until the reading and writing is completed).
Synchronization blocking: after initiating an IO operation, the user process must wait for the IO operation to complete before proceeding to the next operation
Synchronous non blocking: after initiating an IO operation, the user process can do other things while waiting for the return. However, the process needs to ask whether the IO operation is ready from time to time, which will cause a waste of CPU resources
![](https://img-blog.csdnimg.cn/img_convert/5eebc19300d0b1fcbcee052c964d7655.png#align=left&display=inline&height=594&margin=[object Object]&originHeight=594&originWidth=1582&size=0&status=done&style=none&width=1582)
Asynchronous non blocking: the user process can return immediately after initiating an IO operation. After the IO operation is really completed, the application will be notified of the completion of the IO operation. At this time, the user process only needs to process the data. The actual IO read-write operation is not required, because the real IO read-write operation has been completed by the kernel.
Types of IO models
BIO
Synchronize and block. The server implementation mode is one thread per connection, that is, when the client has a connection request, the server needs to start a thread for processing. If the thread does nothing, simply hanging is a waste of thread resources. This problem can be improved through the thread pool mechanism.
NIO
Synchronous non blocking. The server mode is one request and one thread. The requests sent by the client will be registered on the multiplexer. The multiplexer polls that there are I/O requests connected before starting a thread for processing.
AIO
Asynchronous and non blocking. The server implementation mode is one valid request and one thread. The I/O requests of the client are completed by the OS first, and then notify the server to start the thread for processing
Applicable scenarios of different IO models
BIO
BIO is suitable for the architecture with a small number of connections and a fixed number. This method has high requirements for server resources, and concurrency is limited to applications. Jdk1 4 the only choice before, but the program is simple and easy to understand.
NIO
NIO mode is applicable to the architecture with a large number of connections and relatively short connections (light operation), such as chat server, bullet screen system, inter server communication, etc. Programming is complicated, jdk1 4 start support.
AIO
AIO mode is used in architectures with a large number of connections and long connections (reoperation), such as photo album server. It fully calls the OS to participate in concurrent operations. The programming is complex, and JDK7 starts to support it.
On BIO
summary
1.JavaBIO is the traditional Java IO programming, and its related classes and interfaces are in Java io
2.BIO, synchronous blocking communication mode. The server implementation mode is one thread per connection, that is, when the client has a connection request, the server will enable a thread to process it, but you will cause a great waste of thread resources when you don't use it. Just like you pull a special line, which is for you to use. If you are not applicable and others can't use it, the resources of this special line will be wasted. However, this problem can be handled by thread pool, which can reduce some waste.
3.BIO is more suitable for a fixed architecture with a small number of connections. This method requires higher server resources because one connection is requested.
Overview of BIO programming process:
1. The server starts a ServerSocker that listens to the specified port and calls the accept method to wait for the client to communicate
2. The client starts the Socket to communicate with the server process. By default, the server needs to establish a thread to communicate with each client
3. After the client sends a request, first ask the server whether there is a thread response. If not, it will wait or be rejected
4. If there is a response, the client will wait for the end of the thread request before continuing execution
Some easy to understand knowledge points
1. The server socket can be connected with one socket at a time. If multiple clients make connection requests at the same time, the server socket will store the client requesting connection in the queue, and then take out a socket from it to connect with the socket newly created by the server. If the number of requested connections is greater than the maximum capacity, the extra connection requests will be rejected; The default queue size is 50.
Practical operation
Example description:
- Write a server side using BIO model, listen to port 6666, and start a thread to communicate with it when there is a client connection.
- It is required to improve the thread pool mechanism, which can connect multiple clients.
- The server can receive the data sent by the client (telnet).
- Code demonstration:
Implementation code
package com.pjh.BIO; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @ClassName: BIOTest1 * @Author: 86151 * @Date: 2021/6/5 11:58 * @Description: TODO */ public class BIOTest1 { public static void main(String[] args) throws IOException { /*Create a Socket*/ final ServerSocket serverSocket = new ServerSocket(8888); /*Create a thread pool. If there is a client request, create a thread to communicate with it*/ ExecutorService executorService = Executors.newCachedThreadPool(); System.out.println("Server side creation Socket"); /*while Cycle waiting for communication*/ while(true){ //Print thread information System.out.println("Thread information id = " + Thread.currentThread().getId() + "name = " + Thread.currentThread().getName()); //Listen and wait for the client to connect System.out.println("Waiting for connection...."); final Socket socket = serverSocket.accept(); System.out.println("serverSocket.getLocalSocketAddress():"+serverSocket.getLocalSocketAddress()); System.out.println("socket.getLocalSocketAddress():"+socket.getLocalSocketAddress()); /*Take out a thread from the thread pool to communicate with the client*/ executorService.execute(new Runnable() { public void run() { handle(socket); } }); } } public static void handle(Socket socket){ System.out.println("handle"); System.out.println("getLocalSocketAddress():"+socket.getLocalSocketAddress()); System.out.println("socket.getInetAddress():"+socket.getInetAddress()); System.out.println("socket.getLocalAddress():"+socket.getLocalAddress()); try { /*Output thread information*/ System.out.println("Thread information id = " + Thread.currentThread().getId() + "name = " + Thread.currentThread().getName()); byte[] bytes = new byte[1024]; //Get the input stream through socket InputStream inputStream = socket.getInputStream(); /*Loop reading client information*/ while(true){ System.out.println("Thread information id = " + Thread.currentThread().getId() + "name = " + Thread.currentThread().getName()); System.out.println("read...."); int read = inputStream.read(bytes); System.out.println("read:"+read); if (read != -1) { System.out.println(new String(bytes, 0, read));//Output data sent by client } else { break; } } }catch (IOException e) { e.printStackTrace(); }finally { System.out.println("Close the connection to the client"); try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
telnet connection using client
Server side output after connection
In particular, it should be noted that the port to continue listening here is consistent with the port of the socket created, rather than reselecting a port locally for communication as some bloggers on the Internet say.
The client sends a message to the server
problem analysis
-
Each request needs to create an independent thread to Read, process and Write data with the corresponding client.
-
When the number of concurrency is large, a large number of threads need to be created to process the connection, which takes up a large amount of system resources.
3. After the connection is established, if the current thread has no data readable temporarily, the thread will block the Read operation, resulting in a waste of thread resources.