大白话讲Java NIO

文章目录

    • 一、BIO为啥"笨"?NIO为啥"聪明"?
      • [🌰 生活化类比](#🌰 生活化类比)
      • [📊 可视化对比:BIO vs NIO工作流程](#📊 可视化对比:BIO vs NIO工作流程)
        • [1. BIO工作流程(一对一盯桌)](#1. BIO工作流程(一对一盯桌))
        • [2. NIO工作流程(大堂经理统筹)](#2. NIO工作流程(大堂经理统筹))
    • 二、NIO三大核心组件:经理、通道、餐盘
      • [1. Buffer(餐盘):装数据的容器](#1. Buffer(餐盘):装数据的容器)
        • [🌰 类比](#🌰 类比)
        • [📌 核心特点(通俗版)](#📌 核心特点(通俗版))
      • [2. Channel(传菜通道):数据的"双向路"](#2. Channel(传菜通道):数据的“双向路”)
        • [🌰 类比](#🌰 类比)
        • [📌 核心特点(通俗版)](#📌 核心特点(通俗版))
        • [📋 常见的"传菜通道"](#📋 常见的“传菜通道”)
      • [3. Selector(大堂经理):事件"总控"](#3. Selector(大堂经理):事件“总控”)
        • [🌰 类比](#🌰 类比)
        • [📊 Selector工作流程(可视化)](#📊 Selector工作流程(可视化))
  • 三、Selector底层模型

如果把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工作流程(一对一盯桌)

客人点餐-有数据 客人没点餐-无数据 客人到店-客户端连接 分配专属服务员-创建线程 服务员等客人点餐-线程阻塞等数据 服务员上菜-线程处理I/O 客人离店-连接关闭 服务员空闲-线程销毁

BIO的问题:哪怕客人只是占着桌不点餐,服务员也得一直等,100个桌就需要100个服务员,人多了(线程多了),老板(CPU)要花大量精力协调,效率极低。

2. NIO工作流程(大堂经理统筹)

某桌举手-I/O事件就绪 没人举手-无事件 客人到店-客户端连接 登记到经理本上-注册Channel到Selector 经理盯着所有桌-Selector监听事件 派机动服务员处理-线程处理该连接 处理完回经理处-线程回到Selector

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.open 打开传菜通道-Channel 通道设为非阻塞模式 通道找经理登记-register,说要监听读/写事件 经理继续盯通道 经理拿到有动静的通道列表 派服务员处理该通道的事-读/写数据 处理完,服务员回到经理身边

三、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,以下是三种模型的解读:

相关推荐
你怎么知道我是队长39 分钟前
C语言---头文件
c语言·开发语言
期待のcode44 分钟前
Java虚拟机的运行模式
java·开发语言·jvm
程序员老徐1 小时前
Tomcat源码分析三(Tomcat请求源码分析)
java·tomcat
hqwest1 小时前
码上通QT实战25--报警页面01-报警布局设计
开发语言·qt·qwidget·ui设计·qt布局控件
a程序小傲1 小时前
京东Java面试被问:动态规划的状态压缩和优化技巧
java·开发语言·mysql·算法·adb·postgresql·深度优先
仙俊红1 小时前
spring的IoC(控制反转)面试题
java·后端·spring
阿湯哥1 小时前
AgentScope Java 集成 Spring AI Alibaba Workflow 完整指南
java·人工智能·spring
HellowAmy1 小时前
我的C++规范 - 玩一个小游戏
开发语言·c++·代码规范
小楼v1 小时前
说说常见的限流算法及如何使用Redisson实现多机限流
java·后端·redisson·限流算法
与遨游于天地1 小时前
NIO的三个组件解决三个问题
java·后端·nio