文章目录
如果把Java的I/O比作餐厅服务,BIO是“笨办法”(一对一盯桌),NIO是“聪明办法”(一个经理管所有桌)——核心就是用更少的人(线程)干更多的活(处理更多连接)。接下来用生活化的比喻+可视化图表,把NIO讲得明明白白。
一、BIO为啥“笨”?NIO为啥“聪明”?
🌰 生活化类比
| 场景 | BIO(阻塞I/O) | NIO(非阻塞I/O) |
|---|---|---|
| 餐厅对应角色 | 每个餐桌配1个专属服务员(线程) | 1个大堂经理(Selector)+ 若干机动服务员(少量线程) |
| 服务方式 | 服务员站在餐桌旁,直到客人点餐/结账才走(线程阻塞等待I/O) | 经理在前台盯着所有餐桌,只有客人举手(I/O事件就绪)才派服务员过去(线程只处理有数据的连接) |
| 效率 | 100桌需要100个服务员(线程膨胀,成本高) | 100桌只需要1个经理+2-3个服务员(线程复用,成本低) |
| 适用场景 | 客人少、点完就走(低并发、短连接) | 客人多、边吃边加菜(高并发、长连接) |
📊 可视化对比:BIO vs NIO工作流程
1. BIO工作流程(一对一盯桌)
BIO的问题:哪怕客人只是占着桌不点餐,服务员也得一直等,100个桌就需要100个服务员,人多了(线程多了),老板(CPU)要花大量精力协调,效率极低。
2. NIO工作流程(大堂经理统筹)
NIO的核心:经理(Selector)只盯“谁有需求”,服务员(线程)只处理有需求的桌,没人举手时经理就等着,服务员也不闲着——用极少的人搞定大量桌子。
二、NIO三大核心组件:经理、通道、餐盘
NIO的核心就是3个东西:Selector(大堂经理)、Channel(传菜通道)、Buffer(装菜的餐盘),三者配合才能实现“聪明服务”。
1. Buffer(餐盘):装数据的容器
🌰 类比
Buffer就像餐厅里的餐盘——菜(数据)不能直接拿手递,必须装在餐盘里传;客人点的菜(读数据)先放餐盘,服务员端走;要给客人上菜(写数据),也得先把菜装餐盘里。
📌 核心特点(通俗版)
- 餐盘有固定大小(比如只能装10道菜)→ Buffer有
capacity(容量),创建后不能改; - 装菜时从第一个空位开始装→ Buffer有
position(当前装菜位置),装一个菜挪一格; - 装到指定位置就不能装了→ Buffer有
limit(装菜上限),默认等于容量; - 装完菜要递给客人,得先把餐盘“转个向”→ Buffer的
flip()方法(切换为“取菜模式”),把limit设为当前装菜位置,position归0,避免拿空位置。
2. Channel(传菜通道):数据的“双向路”
🌰 类比
Channel就像餐厅里的传菜通道——连接厨房(数据源)和餐桌(程序),而且是双向的(既能从厨房把菜传到餐桌,也能把餐桌的空盘子传回厨房);而BIO的“流”是单向的(要么只传菜,要么只收盘子)。
📌 核心特点(通俗版)
- 双向通行:既能读数据(拿菜),也能写数据(送菜);
- 必须走餐盘:不能直接拿手递菜,所有数据都要通过Buffer(餐盘)传输;
- 可“喊人”:能告诉经理(Selector)“我这有菜要传/要取”(触发I/O事件)。
📋 常见的“传菜通道”
| 通道类型 | 对应场景 | 类比(餐厅) |
|---|---|---|
| FileChannel | 读写本地文件 | 厨房和仓库之间的通道 |
| SocketChannel | 客户端和服务器通信 | 餐厅和客人桌之间的通道 |
| ServerSocketChannel | 服务器监听连接 | 餐厅门口的迎宾通道 |
3. Selector(大堂经理):事件“总控”
🌰 类比
Selector是餐厅的大堂经理——核心工作就是盯着所有传菜通道(Channel),只处理“有动静”的通道:
- 通道注册:所有通道都要在经理这“登记”,告诉经理“我要通知你我这有菜要传(读事件)/要装菜(写事件)”;
- 监听事件:经理啥也不干,就盯着这些通道,直到有通道喊“我这有菜!”(事件就绪);
- 分派任务:哪个通道有动静,就派服务员(线程)去处理这个通道的事,处理完服务员回来继续待命。
📊 Selector工作流程(可视化)
三、Selector底层模型
JVM给Selector做了一层“统一外壳”,底层会调用操作系统提供的“多路复用接口”,不同OS用不同的底层模型:
| 操作系统 | Java NIO底层使用的模型 | 补充说明 |
|---|---|---|
| Linux(2.6+) | epoll(默认最优选择) | 高性能核心,NIO高并发的关键依赖 |
| Linux(2.4及前) | poll(降级选择,无epoll支持) | 老系统兼容,性能一般 |
| Windows | IOCP(I/O Completion Port) | 不是select/poll/epoll,是Windows的“多路复用神器”,效率和epoll相当 |
| macOS/BSD | kqueue | 类似epoll的高效事件通知模型 |
| 其他嵌入式系统 | poll(若不支持epoll/kqueue) | 兼容优先,性能有限 |
在Linux操作系统底层有三种多路复用模型,分别是select、poll、epoll模型,在Linux2.6以后会自动选择epoll,2.4之前则是poll,以下是三种模型的解读:
- select:https://blog.youkuaiyun.com/Tracycoder/article/details/148876497
- poll:https://blog.youkuaiyun.com/Tracycoder/article/details/148892817
- epoll:https://blog.youkuaiyun.com/Tracycoder/article/details/148894195
389

被折叠的 条评论
为什么被折叠?



