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

相关推荐
potato_may41 分钟前
C++ 发展简史与核心语法入门
开发语言·c++·算法
m5655bj1 小时前
通过 C# 将 RTF 文档转换为图片
开发语言·c#
魂梦翩跹如雨1 小时前
P8615 [蓝桥杯 2014 国 C] 拼接平方数——Java解答
java·c语言·蓝桥杯
学习路上_write1 小时前
FREERTOS_任务通知——使用
java·前端·javascript
rabbit_pro1 小时前
Java 文件上传到服务器本地存储
java·服务器·python
5***g2981 小时前
Windows安装Rust环境(详细教程)
开发语言·windows·rust
q_19132846951 小时前
基于Springboot2+Vue2的旅游景点购票系统
java·vue.js·spring boot·后端·mysql·毕业设计·计算机毕业设计
XL's妃妃1 小时前
Java 基准测试工具 JMH 详细介绍
java·开发语言·测试工具