BIO, NIO, and AIO are all I/O models in Java. Their main differences and simple demos are described below.
BIO (Blocking I/O)
BIO is Java’s earliest I/O model, also known as synchronous blocking I/O. In BIO, each I/O operation blocks the current thread and does not continue executing the next statement until the operation is completed, so it has poor concurrency.
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class BlockingIOServer { public static void main(String[] args) { try { //Create ServerSocket and bind port ServerSocket serverSocket = new ServerSocket(8080); while (true) { // Listen for client connections Socket clientSocket = serverSocket.accept(); System.out.println("Accepted connection from client"); // Handle client request handleClientRequest(clientSocket); } } catch (IOException e) { e.printStackTrace(); } } private static void handleClientRequest(Socket clientSocket) throws IOException { InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream(); byte[] buffer = new byte[1024]; int bytesRead; //Read the data sent by the client while ((bytesRead = inputStream.read(buffer)) != -1) { String request = new String(buffer, 0, bytesRead); System.out.println("Received request: " + request); // Process the request and send the response to the client String response = "This is the response from server"; outputStream.write(response.getBytes()); outputStream.flush(); } // Close the stream and connection inputStream.close(); outputStream.close(); clientSocket.close(); } }
The above is an example of a simple server using the blocking I/O model, which listens for client connections on port 8080 and sends a response after receiving a request.
Please note that the I/O operations in this example (inputStream.read()
and outputStream.write()
) are blocking, that is, when there is no data available When reading or writing, the thread will be blocked until data is available or the write is completed.
This is just a basic example. In actual applications, issues such as thread pools, multi-threading, and exception handling may need to be considered to improve performance and stability.
NIO (Non-blocking I/O)
NIO is a new I/O model introduced in Java 1.4, also known as synchronous non-blocking I/O. In NIO, the program polls registered channels through a selector. If a channel has data that can be read or written, corresponding processing will be performed. Because NIO supports multiplexing, a single thread can manage multiple channels simultaneously, improving concurrency performance.
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; public class NonBlockingIOServer { public static void main(String[] args) { try { //Create ServerSocketChannel and bind the port ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress(8080)); serverSocketChannel.configureBlocking(false); //Create Selector and register Channel to Selector Selector selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { // Listen for events selector.select(); // Handle ready events Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectedKeys.iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); if (key.isAcceptable()) { // Handle new connection requests handleAcceptableEvent(serverSocketChannel, selector); } if (key.isReadable()) { // Handle readable events handleReadableEvent(key); } iterator.remove(); } } } catch (IOException e) { e.printStackTrace(); } } private static void handleAcceptableEvent(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException { SocketChannel clientChannel = serverSocketChannel.accept(); clientChannel.configureBlocking(false); clientChannel.register(selector, SelectionKey.OP_READ); System.out.println("Accepted connection from client"); } private static void handleReadableEvent(SelectionKey key) throws IOException { SocketChannel clientChannel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = clientChannel.read(buffer); if (bytesRead == -1) { // connection closed clientChannel.close(); return; } if (bytesRead > 0) { buffer.flip(); byte[] requestData = new byte[buffer.remaining()]; buffer.get(requestData); String request = new String(requestData); System.out.println("Received request: " + request); // handle the request String response = "This is the response from server"; ByteBuffer responseBuffer = ByteBuffer.wrap(response.getBytes()); clientChannel.write(responseBuffer); } } }
The above is an example of a simple server using the non-blocking I/O model, which listens for client connections on port 8080 and sends a response after receiving a request.
This example uses ServerSocketChannel
to accept new connections and configures it in non-blocking mode. Then register ServerSocketChannel
to Selector
and specify to pay attention to the SelectionKey.OP_ACCEPT
event.
In the event loop, first call selector.select()
to listen for events, and then use an iterator to process ready events. For the OP_ACCEPT
event, call the handleAcceptableEvent()
method to handle the new connection request and register the new SocketChannel
to the Selector
on, and specify to pay attention to the SelectionKey.OP_READ
event. For the OP_READ
event, call the handleReadableEvent()
method to read the data sent by the client and process the request.
It should be noted that non-blocking I/O under the NIO model needs to handle more details, such as buffer management, event selection and appropriate thread pools. Only a simple example is provided here. In actual applications, corresponding adjustments and optimizations may be required based on requirements.
AIO (Asynchronous I/O)
AIO is a new I/O model introduced in Java 1.7, also known as asynchronous non-blocking I/O. In AIO, when an I/O operation is performed, the operating system returns immediately and does not block the current thread. When the operation is completed, the operating system will notify the application, and then the application will process the data. Therefore, AIO can effectively utilize CPU time and improve concurrency performance.
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousChannelGroup; import java.nio.channels.AsynchronousServerSocketChannel; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; import java.util.concurrent.Executors; public class AsyncIOServer { private static final int PORT = 8080; public static void main(String[] args) throws IOException { AsynchronousChannelGroup channelGroup = AsynchronousChannelGroup.withThreadPool(Executors.newFixedThreadPool(10)); AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open(channelGroup); serverSocketChannel.bind(new InetSocketAddress(PORT)); serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() { @Override public void completed(AsynchronousSocketChannel clientChannel, Void attachment) { // Handle new connections serverSocketChannel.accept(null, this); handleClientChannel(clientChannel); } @Override public void failed(Throwable exc, Void attachment) { exc.printStackTrace(); } }); } private static void handleClientChannel(AsynchronousSocketChannel clientChannel) { ByteBuffer buffer = ByteBuffer.allocate(1024); clientChannel.read(buffer, null, new CompletionHandler<Integer, Void>() { @Override public void completed(Integer bytesRead, Void attachment) { if (bytesRead == -1) { try { clientChannel.close(); } catch (IOException e) { e.printStackTrace(); } return; } if (bytesRead > 0) { buffer.flip(); byte[] requestData = new byte[buffer.remaining()]; buffer.get(requestData); String request = new String(requestData); System.out.println("Received request: " + request); // handle the request String response = "This is the response from server"; ByteBuffer responseBuffer = ByteBuffer.wrap(response.getBytes()); clientChannel.write(responseBuffer, null, new CompletionHandler<Integer, Void>() { @Override public void completed(Integer bytesWritten, Void attachment) { if (responseBuffer.hasRemaining()) { clientChannel.write(responseBuffer, null, this); } else { try { clientChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } @Override public void failed(Throwable exc, Void attachment) { exc.printStackTrace(); } }); } } @Override public void failed(Throwable exc, Void attachment) { exc.printStackTrace(); } }); } }
The above is an example of a simple server using the asynchronous I/O model, which listens for client connections on port 8080 and sends a response after receiving a request.
This example uses AsynchronousServerSocketChannel
to accept new connections and configure it in asynchronous mode. Then, call the accept()
method to receive the new connection, passing the CompletionHandler
instance as a parameter, and handle the new connection request in the callback function. For an established connection, use the read()
method to read the data sent by the client, pass the CompletionHandler
instance as a parameter, and process the request in the callback function.
It should be noted that programming under the asynchronous I/O model is relatively complex and requires proficiency in the use of CompletionHandler
, as well as how to manage buffers and event selection. Only a simple example is provided here. In actual applications, corresponding adjustments and optimizations may be required based on requirements.
To sum up, BIO, NIO, and AIO are all I/O models in Java. Their main difference lies in the way they handle I/O operations. BIO is a synchronous blocking model, and each I/O operation blocks the current thread; NIO is a synchronous non-blocking model, which implements multiplexing through selector polling registered channels, improving concurrency performance; AIO is an asynchronous non-blocking model, The operating system returns immediately and does not block the current thread, which can effectively utilize CPU time and further improve concurrency performance. Therefore, it is very important to choose the appropriate I/O model based on actual application scenarios and requirements.
For more news and information, please visit Ayshuju Data (https://www.ayshuju.com/home)