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

"Java NIO 不是 AIO

Java 有 3 套 I/O API

  • 传统 I/O(java.io)= BIO(同步阻塞)
  • Java NIO(java.nio,1.4+)= NIO(同步非阻塞)
  • Java AIO(AsynchronousChannel,1.7+)= AIO(异步非阻塞)

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 NIO Java AIO
全称 New I/O Asynchronous I/O
引入版本 Java 1.4(2002) Java 1.7(2011)
同步性 同步(用户线程查询 I/O 状态) 异步(OS 通知用户线程)
阻塞性 非阻塞(用户线程立即返回) 非阻塞(用户线程立即返回)
通知方式 epoll 事件驱动(用户线程要 selector.select() 查询) OS 异步回调用户线程不用查询
Channel + Buffer + Selector AsynchronousChannel + 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 主动回调(异步)

注意

  • NIO 的 epoll = OS 内核通知用户线程有 fd 就绪
  • 但用户线程还要主动 select() 查询同步
  • AIO = OS 内核主动回调真正异步
  • NIO 的"回调"AIO 的"回调"
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))

核心洞察

  • Linux 上 AIO 不成熟(glibc AIO 性能差)
  • Linux 上 epoll 极好(30+ 年优化)
  • 所以 Java NIO(基于 epoll)性能 > Java AIO(基于 Linux AIO)
  • MOVA / Gateway / Redis / Kafka 都不用 AIO——用 NIO + epoll
5.2 实际数据
指标 Java NIO + epoll Java 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/O Java NIO Java AIO
java.io java.nio java.nio.channels.AsynchronousXxx
模型 同步阻塞BIO 同步非阻塞NIO 异步非阻塞AIO
核心类 Stream / Socket Channel / Buffer / Selector AsynchronousChannel / CompletionHandler
项目 老项目 Gateway / Redis / Kafka ❌ 不用

八、项目实战对照

8.1 NIO 实战
项目 实现方式 语言 用了什么
Spring Cloud Gateway Netty 封装 Java NIO(epoll) Java Netty + Java NIO + epoll
Redis 6.0+ C 语言原生实现(不用 Java NIO) C ae + epoll(不用 Java NIO
Kafka 1.0+ 直接用 Java NIO(没有 Netty 封装) Java Java NIO + epoll(不用 Netty
8.3 AIO 实战
  • 不用(Linux 上 AIO 不如 NIO)
  • 只在 Windows 上有性能优势(IOCP)

九、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();

注意

  • Java AIO API 复杂CompletionHandler / Future 两套 API
  • 实际项目用得少
  • 面试了解即可

十、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

  • 传统 I/O(java.io)= BIO(同步阻塞)
  • Java NIO(java.nio)= NIO同步非阻塞 + epoll 事件驱动
  • Java AIO(AsynchronousChannel)= AIO异步非阻塞

NIO 和 AIO 的核心区别

  • NIO = 用户线程主动 select() 查询同步
  • AIO = OS 内核主动回调真正异步

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

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐