跳转至

Java NIO 高频面试考点汇总

一、NIO 三大核心组件

组件 作用
Channel 双向通道,类比 Stream,但可读可写
Buffer 数据容器,Channel 读写都经过 Buffer
Selector 单线程监听多个 Channel 的事件(多路复用)

经典模型:一个 Selector 线程管理多个 Channel,每个 Channel 注册感兴趣的事件。

二、Channel 的主要实现

  • FileChannel:文件读写,阻塞,不能切换非阻塞。
  • SocketChannel / ServerSocketChannel:TCP。
  • DatagramChannel:UDP。

三、Buffer 的核心概念

四个属性:

capacity   容量
limit      读写上限
position   当前位置
mark       标记

关键方法:

ByteBuffer buf = ByteBuffer.allocate(1024);
buf.put((byte) 1);
buf.flip();      // 写转读:limit = position, position = 0
buf.get();
buf.clear();     // 读转写:position = 0, limit = capacity(不真正清数据)
buf.compact();   // 把未读数据移到开头,继续写

flip 和 clear 的区别

  • flip():读之前调用,把 limit 设为当前 position,position 归零。
  • clear():读之后调用,position 归零、limit = capacity,数据还在但被覆盖。
  • rewind():只把 position 归零,limit 不变(重读)。

四、Selector 多路复用

Selector selector = Selector.open();
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);

while (true) {
    int ready = selector.select();
    Set<SelectionKey> keys = selector.selectedKeys();
    Iterator<SelectionKey> it = keys.iterator();
    while (it.hasNext()) {
        SelectionKey k = it.next();
        it.remove();
        if (k.isReadable()) { ... }
        else if (k.isWritable()) { ... }
    }
}

四种事件:OP_READOP_WRITEOP_CONNECTOP_ACCEPT

五、BIO vs NIO vs AIO

BIO NIO AIO
模式 同步阻塞 同步非阻塞 异步非阻塞
流向 流式 缓冲式 缓冲式
核心 Stream Channel+Buffer+Selector Future/Callback
适用 连接少、短连接 连接多、轻量 连接多、操作重

六、零拷贝

传统数据传输:磁盘 → 内核缓冲区 → 用户态 → Socket 缓冲区 → 协议栈,4 次拷贝、4 次上下文切换。

NIO 的 FileChannel.transferTo() 使用 sendfile 系统调用,数据直接在内核态从文件描述符传到 Socket,CPU 不参与。Netty 的 FileRegion 也是这个原理。

七、Netty 为什么快

  • 基于 NIO,主从 Reactor 线程模型。
  • 零拷贝:CompositeByteBuftransferTo
  • 内存池:ByteBuf 池化减少 GC。
  • 高效编解码。

高频追问

  • 为什么 FileChannel 不能非阻塞?文件 IO 本来就没有"等待连接"的概念。
  • Selector 在 Linux 上用 epoll,Windows 上用 select/POLL。epoll 比 select 快在:无 FD 上限、回调而非轮询。