
第一部分宏观视角——什么是 I/O 模型在计算机世界里I/OInput/Output即输入/输出。从内核角度看所有的 I/O 最终都是在操作系统内核中进行的。对于一次网络输入数据会先到达网卡然后拷贝到内核空间最后由应用程序从内核空间拷贝到用户空间。从模型角度看I/O 模型解决的是“当数据还没准备好时线程是等阻塞还是不等非阻塞”以及“当数据准备好了是谁负责搬运同步还是异步”的问题。第二部分四大模型深度对峙——从 BIO 到 AIO1. BIO (Blocking I/O) - 同步阻塞特征一个连接对应一个线程。如果数据没来线程就一直挂起。瓶颈线程资源昂贵。面对 10 万个并发连接系统无法开 10 万个线程必然崩溃。适用连接数少且固定的架构。2. NIO (Non-blocking I/O) - 同步非阻塞特征线程发起请求后立即返回。如果数据没准备好就不断轮询Polling。瓶颈轮询操作极度消耗 CPU且大部分轮询是无效的。3. I/O Multiplexing (I/O 多路复用) - 现代高并发的基石这是Redis、Nginx、Netty的核心。它通过select/epoll系统调用让一个线程同时监控成千上万个文件描述符FD。select线性扫描所有 FD有上限限制通常 1024效率随连接数增加而下降。epoll (Linux 2.6)事件驱动。只有真正活跃的连接会触发回调效率极高没有连接上限。4. AIO (Asynchronous I/O) - 异步非阻塞特征应用告知内核“我要读数据”然后去忙别的。内核把数据准备好并拷贝到用户空间后再通知应用。现状Java AIO 在 Windows 上支持良好但在 Linux 上底层实现仍是 epoll 模拟性能提升不明显因此目前主流仍是 NIO。第三部分Java NIO 三剑客——Buffer、Channel、Selector如果说 BIO 是基于“流Stream”的那么 NIO 就是基于“块Block”的。1. Buffer (缓冲区)NIO 所有的操作都是通过缓冲区。它本质上是一个数组但提供了position、limit、capacity三个指针来控制读写。2. Channel (通道)类似于 BIO 中的流但 Channel 是双向的。既可以读也可以写。3. Selector (选择器)Selector 是多路复用的核心。它能检测多个注册在上面的 Channel 是否有事件发生如连接、读、写。 Java 代码演示手写一个 NIO 服务端JavaSelector selector Selector.open(); ServerSocketChannel serverChannel ServerSocketChannel.open(); serverChannel.bind(new InetSocketAddress(8080)); serverChannel.configureBlocking(false); // 必须设置为非阻塞 serverChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { selector.select(); // 阻塞等待事件发生 SetSelectionKey keys selector.selectedKeys(); IteratorSelectionKey iter keys.iterator(); while (iter.hasNext()) { SelectionKey key iter.next(); if (key.isAcceptable()) { // 处理新连接... } else if (key.isReadable()) { // 读取数据... } iter.remove(); // 必须移除否则会重复触发 } }第四部分面试复盘脑图Code snippetmindmap root((Java IO 模型)) 分类 BIO: 一连接一线程, 阻塞严重 NIO: 缓冲区通道, 选择器多路复用 AIO: 事件回调, 真正的异步 NIO 三要素 Buffer: 数据载体 (flip/clear/rewind) Channel: 传输通道 (File/Socket/Datagram) Selector: 多路复用器 (基于 epoll) 多路复用演进 Select: 线性轮询, 1024限制 Poll: 线性轮询, 无限制但慢 Epoll: 事件通知, 响应式, O(1) 复杂度 核心对比 阻塞 vs 非阻塞: 线程是否挂起 同步 vs 异步: 数据拷贝由谁完成 (内核 or 用户) 实战应用 Netty: 封装 NIO, 解决粘包/半包, Reactor 模式 Redis: 单线程多路复用 Kafka: 零拷贝 (sendfile) NIO第五部分大厂面试官的“夺命三连问”为什么 Netty 不使用 AIO 而是坚持使用 NIO回答要点Linux 平台下 AIO 底层依然是 epoll 封装没有本质性能飞跃。AIO 编程模型极其复杂。NIO 配合 Reactor 模式已经足够支撑百万级并发性价比更高。epoll 的“水平触发LT”和“边缘触发ET”有什么区别回答要点LT (Level Trigger)只要缓冲区有数据内核就不断提醒你。ET (Edge Trigger)只有数据从无到有时才提醒一次。性能更高但要求应用必须一次性把数据读完否则容易丢失事件。零拷贝Zero-Copy在 NIO 中是如何体现的回答要点NIO 提供了DirectBuffer直接内存和FileChannel.transferTo()。通过调用操作系统底层的sendfile数据可以在内核态直接从磁盘读入网卡无需经过 CPU 拷贝到用户空间极大提升了吞吐。结语IO 是高并发架构的底座我深刻体会到所有的业务代码最终都要跑在 IO 上。你理解了 IO 模型就理解了为什么数据库连接池要设得那么小理解了为什么 Kafka 读写那么快也理解了为什么在高并发场景下线程池的参数不能乱设。这篇文章是 IO 模型的最核心总结。如果你能结合这些知识点在面试中自信地聊聊 Reactor 模型Single Threaded vs Multi Threaded那么架构师的 Offer 已经在向你招手了。