java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java NIO和AIO区别

Java NIO和Java AIO的区别解析

作者:swordbob

这篇文章给大家介绍了Java NIO和Java AIO的区别解析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

一、Java NIO 是 NIO,Java AIO 才是 AIO

"Java NIO 不是 AIO

Java 有 3 套 I/O API

Java NIO 是 NIO——底层用 epoll。Java AIO 是 AIO"——实际用得很少。"

二、Java 3 大 I/O API 严格分类

┌──────────────────────────────────────────────────┐
│  Java 3 大 I/O API 严格分类                        │
├──────────────────────────────────────────────────┤
│                                                   │
│  1. 传统 I/O(java.io)                          │
│     └─ 同步阻塞 I/O = BIO                         │
│     └─ 老项目 / 简单场景                          │                             │
│                                                   │
│  2. Java NIO(java.nio,1.4+)                    │
│     └─ 同步非阻塞 I/O = NIO                       │
│     └─ 多路复用 + Channel + Buffer + Selector    │
│     └─ ⚠️ 底层 Linux 用 epoll(事件驱动回调)     │
│     └─ ⚠️ **同步**(用户线程要查询 I/O 状态)      │
│     └─ Spring Cloud Gateway / Netty / Redis / Kafka│
│                                                   │
│  3. Java AIO(AsynchronousChannel,1.7+)          │
│     └─ 异步非阻塞 I/O = AIO                       │
│     └─ 异步回调 / Future                          │
│     └─ ❌ 实际用得很少(**Linux 上 AIO 不如 NIO**)│
│                                                   │
└──────────────────────────────────────────────────┘


三、Java NIO vs Java AIO 4 大核心区别

维度Java NIOJava AIO
全称New I/OAsynchronous I/O
引入版本Java 1.4(2002)Java 1.7(2011)
同步性同步(用户线程查询 I/O 状态)异步(OS 通知用户线程)
阻塞性非阻塞(用户线程立即返回)非阻塞(用户线程立即返回)
通知方式epoll 事件驱动(用户线程要 selector.select() 查询)OS 异步回调用户线程不用查询
Channel + Buffer + SelectorAsynchronousChannel + CompletionHandler / Future
底层epoll(Linux)AIO(Linux)/ IOCP(Windows)
性能(Linux)⚠️⚠️⚠️ 极好⚠️ 反而不如 NIO
使用场景主流(高并发)理论强,实际不用

四、"epoll 是回调"为什么对(NIO 不是 AIO)

4.1 NIO 的"事件驱动" ≠ AIO 的"异步回调"

关键差异

NIO(同步非阻塞):
用户线程:selector.select()  ← ⚠️ 用户线程主动查询
    ↓
epoll_wait() 返回就绪的 fd
    ↓
用户线程遍历处理
    ↓
⚠️ 用户线程主动查询(同步)
AIO(异步非阻塞):
用户线程:channel.read(buffer, callback)  ← ⚠️ 用户线程不查询
    ↓
OS 内核后台读
    ↓
读完后 OS 内核**主动回调** callback  ← ⚠️ OS 主动回调(异步)

注意

4.2 用代码严格对比

// ========== NIO(同步非阻塞)==========
// 老哥 MOVA / Gateway 用的
Selector selector = Selector.open();
while (true) {
    // ⚠️ 用户线程主动查询
    int ready = selector.select();  // 用户线程主动调用
    if (ready == 0) continue;
    // 用户线程处理
    Set<SelectionKey> keys = selector.selectedKeys();
    for (SelectionKey key : keys) {
        // 处理就绪的 fd
    }
}
// ⚠️ 用户线程主动 select() —— 同步
// ========== AIO(异步非阻塞)==========
// 老哥基本不用
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
// ⚠️ 用户线程不查询,OS 回调
channel.read(buffer, attachment, new CompletionHandler<Integer, ByteBuffer>() {
    @Override
    public void completed(Integer len, ByteBuffer buf) {
        // ⚠️ OS 内核完成后主动回调
    }
    @Override
    public void failed(Throwable exc, ByteBuffer attachment) {
        // ⚠️ OS 内核失败时主动回调
    }
});
// ⚠️ 用户线程不查询 —— 真正异步

五、为什么 Java NIO 在 Linux 上比 Java AIO 性能好(核心)

5.1 根本原因

Linux 内核 AIO 实现:
- ❌ 不成熟(glibc AIO 性能差)
- ❌ 只支持 O_DIRECT 模式(绕过 Page Cache)
- ❌ 不能用于普通文件 I/O
- ❌ 不能用于网络 I/O
Linux 内核 epoll 实现:
- ✅ 成熟稳定(30+ 年历史)
- ✅ 支持文件 / 网络 / 设备 / 管道
- ✅ 性能极佳(O(1))

核心洞察

5.2 实际数据

指标Java NIO + epollJava AIO
并发连接10w+1w-(实际上不如 NIO
吞吐量⚠️⚠️⚠️ 极好⚠️ 一般
延迟微秒级微秒级(Linux 不好)
项目✅ Gateway / Redis / Kafka❌ 不用

六、3 大 I/O API 真实使用情况

API真实使用情况
传统 I/O(java.io)所有老项目
Java NIO(java.nio)现代 Java 主流
Java AIO(AsynchronousChannel)基本不用

七、3 大 I/O API 4 大核心差异

维度传统 I/OJava NIOJava AIO
java.iojava.niojava.nio.channels.AsynchronousXxx
模型同步阻塞BIO同步非阻塞NIO异步非阻塞AIO
核心类Stream / SocketChannel / Buffer / SelectorAsynchronousChannel / CompletionHandler
项目老项目Gateway / Redis / Kafka❌ 不用

八、项目实战对照

8.1 NIO 实战

项目实现方式语言用了什么
Spring Cloud GatewayNetty 封装 Java NIO(epoll)JavaNetty + Java NIO + epoll
Redis 6.0+C 语言原生实现(不用 Java NIO)Cae + epoll(不用 Java NIO
Kafka 1.0+直接用 Java NIO(没有 Netty 封装)JavaJava NIO + epoll(不用 Netty

8.3 AIO 实战

九、Java AIO 4 大核心 API(了解即可)

// 1. AsynchronousFileChannel(异步文件 I/O)
AsynchronousFileChannel channel = AsynchronousFileChannel.open(
    Paths.get("test.txt"), 
    StandardOpenOption.READ
);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Future<Integer> result = channel.read(buffer, 0);
// ⚠️ 异步返回 Future
result.get();  // 阻塞等待完成(**不推荐**)
// 2. AsynchronousSocketChannel(异步 TCP 客户端)
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
Future<Void> connectFuture = client.connect(new InetSocketAddress("localhost", 8080));
// 3. AsynchronousServerSocketChannel(异步 TCP 服务端)
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();
server.bind(new InetSocketAddress(8080));
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
    @Override
    public void completed(AsynchronousSocketChannel client, Void attachment) {
        // 异步回调
    }
});
// 4. AsynchronousDatagramChannel(异步 UDP)
AsynchronousDatagramChannel udpChannel = AsynchronousDatagramChannel.open();

注意

十、7 大追问完整串起来

1. 什么是轮询?
   └─ 软件层面:客户端反复问服务器
2. NIO 多路复用中的轮询?
   └─ OS 层面:select/poll 是真轮询,epoll 是事件驱动回调
3. NIO 的 Channel 里有多 BIO 吗?
   └─ ❌ 没有,Channel 是 fd 的 Java 包装
4. 一个 Selector 同一时间能处理几个 Channel?
   └─ 理论上无限个,实际上同时 1 个(单线程串行)
5. 什么是 fd(File Descriptor)?
   └─ Linux 内核的整数 ID
   └─ 一切 I/O 都是 fd
   └─ NIO Channel = fd 的 Java 包装
6. Java NIO 用 epoll 还是 select/poll?
   └─ Linux 下默认 epoll(**不是 select/poll**)
   └─ epoll 是事件驱动(**回调**),不是轮询
   └─ 老哥说"epoll 是回调"完全正确 ✅
7. Java NIO 是 AIO 吗?
   └─ ❌ **不是**!Java NIO 是 NIO,Java AIO 才是 AIO
   └─ Java NIO 是**同步**非阻塞(用户线程要 select() 查询)
   └─ Java AIO 是**异步**非阻塞(OS 内核**主动回调**)
   └─ Java AIO 实际不用(**Linux 上 AIO 不如 NIO**)

十一、NIO vs AIO 最终版

"Java NIO 不是 AIO

Java 有 3 套 I/O API

NIO 和 AIO 的核心区别

Gateway / Redis / Kafka 用的都是 Java NIO——不是 AIOJava AIO 实际不用——Linux 上 AIO 性能不如 NIO(glibc AIO 不成熟)。"

到此这篇关于Java NIO和Java AIO的区别解析的文章就介绍到这了,更多相关Java NIO和AIO区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文