BIO、NIO、AIO 有什么区别

简介: BIO(阻塞I/O)模型中,服务器实现模式为一个连接一个线程;NIO(非阻塞I/O)使用单线程或少量线程处理多个请求;AIO(异步I/O)则是在NIO基础上进一步优化,采用事件通知机制,提高并发处理能力。
  1. BIO(Blocking I/O,阻塞式I/O)
    • 概念与原理
      • BIO是一种最基本的I/O模型。当一个线程发起一个I/O操作(如读取文件或网络通信)时,该线程会被阻塞,直到这个I/O操作完成。例如,在进行网络通信时,服务器端使用ServerSocket来监听端口,当有客户端连接请求时,accept方法会阻塞,直到有新的连接建立。之后,在读取或写入数据时,readwrite方法也会阻塞线程,直到数据读取或写入完成。
    • 代码示例(以Java网络编程为例)
      ```java
      import java.io.IOException;
      import java.io.InputStream;
      import java.net.ServerSocket;
      import java.net.Socket;

public class BIOServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器已启动,等待客户端连接...");
// 阻塞,等待客户端连接
Socket socket = serverSocket.accept();
System.out.println("客户端已连接");
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
// 阻塞,等待读取数据
int length = inputStream.read(buffer);
System.out.println("收到客户端消息:" + new String(buffer, 0, length));
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

   - **应用场景与优缺点**:
     - **应用场景**:适用于连接数比较少且连接比较稳定的场景,如简单的文件传输服务、数据库连接等。因为它的编程模型简单直接,容易理解和实现。
     - **优点**:编程模型简单,对于初学者来说容易上手;在处理少量连接时,性能可以满足需求。
     - **缺点**:一个线程只能处理一个连接,当连接数增多时,需要创建大量的线程来处理,会导致系统资源的浪费(线程上下文切换开销等);线程阻塞会导致效率低下,特别是在等待I/O操作完成的过程中,线程无法执行其他任务。

2. **NIO(Non - Blocking I/O,非阻塞式I/O)**
   - **概念与原理**:
     - NIO是一种基于通道(Channel)和缓冲区(Buffer)的I/O模型。与BIO不同,在NIO中,线程发起I/O操作后不会被阻塞。例如,通道在进行数据读取或写入操作时,如果没有数据可读或可写,不会像BIO那样阻塞线程,而是会返回一个特殊的值(如`-1`表示没有数据可读),这样线程就可以去做其他事情。NIO还引入了选择器(Selector),它可以同时监听多个通道的事件(如可读、可写、连接等事件),从而实现一个线程管理多个I/O通道。
   - **代码示例(以Java NIO网络编程为例)**:
```java
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 NIOServer {
    public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(8080));
            serverSocketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("服务器已启动,等待客户端连接...");
            while (true) {
                // 阻塞,等待事件发生
                int readyChannels = selector.select();
                if (readyChannels == 0) continue;
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();
                    if (key.isAcceptable()) {
                        ServerSocketChannel server = (ServerSocketChannel) key.channel();
                        SocketChannel socketChannel = server.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    } else if (key.isReadable()) {
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        int length = socketChannel.read(buffer);
                        if (length > 0) {
                            buffer.flip();
                            System.out.println("收到客户端消息:" + new String(buffer.array(), 0, length));
                        }
                    }
                    keyIterator.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 应用场景与优缺点
    • 应用场景:适用于高并发的网络应用,如高性能的网络服务器、大规模的文件读写等场景。因为它可以用较少的线程来处理多个连接,提高了资源利用率和系统的吞吐量。
    • 优点:一个线程可以管理多个连接,减少了线程上下文切换的开销,提高了系统资源的利用率;非阻塞的I/O操作可以让线程在等待I/O操作时去处理其他任务,提高了系统的并发性能。
    • 缺点:编程模型相对复杂,需要理解通道、缓冲区和选择器等概念;在处理复杂的业务逻辑时,可能需要更多的代码来处理各种I/O事件和状态。
  1. AIO(Asynchronous I/O,异步I/O)
    • 概念与原理
      • AIO是一种真正的异步I/O模型。在AIO中,当线程发起一个I/O操作后,线程可以继续执行其他任务,而不需要等待I/O操作完成。当I/O操作完成后,系统会通过回调函数或者事件通知的方式来告知线程操作已经完成。这种方式进一步提高了系统的并发性能,因为线程完全不需要在I/O操作上等待。
    • 代码示例(以Java AIO网络编程为例)
      ```java
      import java.io.IOException;
      import java.net.InetSocketAddress;
      import java.nio.ByteBuffer;
      import java.nio.channels.AsynchronousServerSocketChannel;
      import java.nio.channels.AsynchronousSocketChannel;
      import java.nio.channels.CompletionHandler;
      import java.util.concurrent.CountDownLatch;

public class AIOServer {
public static void main(String[] args) {
try {
AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8080));
final CountDownLatch latch = new CountDownLatch(1);
System.out.println("服务器已启动,等待客户端连接...");
serverSocketChannel.accept(null, new CompletionHandler() {
@Override
public void completed(AsynchronousSocketChannel socketChannel, Object attachment) {
try {
serverSocketChannel.accept(null, this);
ByteBuffer buffer = ByteBuffer.allocate(1024);
socketChannel.read(buffer, buffer, new CompletionHandler() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
if (result > 0) {
attachment.flip();
System.out.println("收到客户端消息:" + new String(attachment.array(), 0, result));
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
exc.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Object attachment) {
exc.printStackTrace();
try {
latch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
});
latch.await();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
```

  • 应用场景与优缺点
    • 应用场景:适用于对性能要求极高、处理大量并发I/O操作的场景,如大型分布式系统中的高性能网络通信、海量数据存储系统等。
    • 优点:真正实现了I/O操作与线程执行的异步,最大限度地提高了系统的并发性能;通过回调函数或事件通知的方式,使得代码在处理I/O完成后的逻辑时更加灵活。
    • 缺点:编程模型最复杂,需要对异步编程的概念和回调机制有深入的理解;不同操作系统对AIO的支持程度可能不同,可能会导致在某些系统上性能不如预期或者实现起来比较困难。
相关文章
|
1月前
|
网络协议 Dubbo Java
一文搞懂NIO、AIO、BIO的核心区别(建议收藏)
本文详细解析了NIO、AIO、BIO的核心区别,NIO的三个核心概念,以及NIO在Java框架中的应用等。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
一文搞懂NIO、AIO、BIO的核心区别(建议收藏)
|
1月前
|
消息中间件 监控 Java
BIO、NIO、AIO在不同场景下的应用对比
BIO(阻塞I/O)、NIO(非阻塞I/O)和AIO(异步I/O)是Java中处理I/O操作的三种模式。BIO适用于连接数少且稳定的场景;NIO通过非阻塞模式提高并发处理能力,适合高并发场景;AIO则完全异步,适合需要高效、低延迟的I/O操作场景。
102 4
|
5月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
7月前
|
存储 监控 Java
深入探索Java语言的NIO(New I/O)技术
深入探索Java语言的NIO(New I/O)技术
|
5月前
|
Java
Java中的NIO编程详解
Java中的NIO编程详解
|
5月前
|
Java 大数据
如何在Java中进行网络编程:Socket与NIO
如何在Java中进行网络编程:Socket与NIO
|
5月前
|
Java
Java中的NIO编程详解
Java中的NIO编程详解
|
6月前
|
存储 监控 Java
Java中的NIO编程实践精华
Java中的NIO编程实践精华
|
6月前
|
Java 视频直播 数据库连接
Java I/O 模型详解:BIO、NIO 与 AIO 的特性与应用
Java I/O 模型详解:BIO、NIO 与 AIO 的特性与应用
74 2
|
6月前
|
存储 网络协议 Java
Java I/O 详解:基础、文件操作与 NIO 实践
Java I/O 详解:基础、文件操作与 NIO 实践
68 1