当前位置: 首页 > news >正文

IO模型有哪几种

 Java / 后端开发中核心的 IO 模型分类,是网络编程、高并发开发的基础知识点。主流的 IO 模型分为5 类(从最基础的阻塞 IO 到高性能的异步 IO),本文用通俗易懂的语言从浅到深讲解,结合场景和比喻快速理解。
 

一、IO 模型的核心分类(按 UNIX/POSIX 标准定义)

先明确核心概念:IO 操作的本质是「数据从内核缓冲区到用户缓冲区」的拷贝过程,IO 模型的差异体现在等待数据阶段和拷贝数据阶段的阻塞 / 非阻塞特性。

1. 阻塞 IO(Blocking IO,BIO)

  • 通俗比喻:你去奶茶店点单,点完后站在柜台前一直等,直到拿到奶茶(期间不能做任何事)。
  • 核心逻辑:
    • 应用程序发起 IO 请求(如读取网络数据)后,全程阻塞:
      ① 等待内核准备好数据(比如网卡接收到数据并写入内核缓冲区);
      ② 内核将数据拷贝到用户缓冲区。
    • 直到整个过程完成,线程才解除阻塞。
     
  • 代码示例(Java BIO):
    java
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;// BIO服务端:一个连接对应一个线程,线程全程阻塞等待数据
    public class BIOExample {public static void main(String[] args) throws Exception {ServerSocket serverSocket = new ServerSocket(8080);System.out.println("BIO服务端启动,等待连接...");while (true) {// 阻塞:等待客户端连接Socket socket = serverSocket.accept(); // 新建线程处理该连接(否则无法接收下一个连接)new Thread(() -> {try {InputStream in = socket.getInputStream();byte[] buf = new byte[1024];// 阻塞:等待数据并拷贝到用户缓冲区int len = in.read(buf); if (len > 0) {System.out.println("收到数据:" + new String(buf, 0, len));}in.close();socket.close();} catch (Exception e) {e.printStackTrace();}}).start();}}
    }
     
  • 特点:简单易实现,但线程资源消耗极大(高并发下会创建大量线程),性能差。
  • 适用场景:连接数少、并发低的场景(如简单的本地文件读取)。

2. 非阻塞 IO(Non-Blocking IO,NIO)

  • 通俗比喻:你点完奶茶后,不站在柜台等,而是每隔 1 分钟去问一次 “我的奶茶好了吗?”(轮询),期间可以刷手机、聊天。
  • 核心逻辑:
    • 应用程序发起 IO 请求后,立即返回(不阻塞):
      ① 若内核数据未准备好,返回「未就绪」状态,应用程序需要不断轮询检查;
      ② 一旦数据准备好,内核拷贝数据到用户缓冲区(此阶段仍阻塞)。
  • 特点:线程无需一直等待,但轮询会消耗 CPU 资源,效率依然不高。
  • 适用场景:连接数较少、需要快速响应的简单场景(极少单独使用)。

3. IO 多路复用(IO Multiplexing,也叫多路转接)

  • 通俗比喻:你点完奶茶后,告诉店员 “好了叫我”,然后坐在座位上;同时还有 10 个人也点了奶茶,店员统一管理所有订单,做好后逐个喊人取(一个店员管理多个订单)。
  • 核心逻辑:
    • 引入「IO 多路复用器」(如 Linux 的select/poll/epoll、Java 的Selector),一个线程可以监听多个 IO 通道:
      ① 应用程序将所有待监听的 IO 通道注册到复用器上,线程阻塞在复用器上(而非单个 IO 通道);
      ② 当任意 IO 通道的数据准备好,复用器会通知线程,线程再去处理对应的 IO(拷贝数据阶段仍阻塞)。
     
  • Java NIO 就是基于此模型,代码示例(核心片段):
    java
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;// NIO多路复用核心逻辑
    public class NIOSelectorExample {public static void main(String[] args) throws Exception {// 1. 创建多路复用器(Selector)Selector selector = Selector.open();// 2. 创建服务端通道并注册到SelectorServerSocketChannel serverChannel = ServerSocketChannel.open();serverChannel.bind(new java.net.InetSocketAddress(8080));serverChannel.configureBlocking(false); // 设置为非阻塞serverChannel.register(selector, java.nio.channels.SelectionKey.OP_ACCEPT);while (true) {// 3. 阻塞:等待有就绪的IO事件(连接/数据可读)selector.select(); // 4. 遍历所有就绪的事件并处理for (java.nio.channels.SelectionKey key : selector.selectedKeys()) {if (key.isAcceptable()) {// 处理新连接SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();clientChannel.configureBlocking(false);// 注册读事件clientChannel.register(selector, java.nio.channels.SelectionKey.OP_READ);} else if (key.isReadable()) {// 处理数据读取(拷贝阶段仍阻塞,但仅针对就绪的通道)SocketChannel clientChannel = (SocketChannel) key.channel();java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(1024);int len = clientChannel.read(buf);if (len > 0) {System.out.println("收到数据:" + new String(buf.array(), 0, len));}clientChannel.close();}}selector.selectedKeys().clear(); // 清空已处理的事件}}
    }
     
  • 特点:一个线程管理多个 IO 通道,CPU 利用率高,是高并发网络编程的基础(如 Nginx、Netty 底层)。
  • 关键区别:select/poll(轮询所有注册通道)效率低于epoll(事件通知机制),Java NIO 在 Linux 下默认用 epoll。

4. 信号驱动 IO(Signal Driven IO,SIGIO)

  • 通俗比喻:你点完奶茶后留了手机号,店员做好后给你发个短信,你收到短信后去柜台取奶茶。
  • 核心逻辑:
    • 应用程序通过「信号机制」注册 IO 事件,然后线程继续执行其他任务;
    • 内核数据准备好后,向应用程序发送SIGIO信号,应用程序收到信号后,再发起 IO 调用(拷贝数据阶段阻塞)。
     
  • 特点:无需轮询,但信号处理逻辑复杂,Java 中几乎不直接使用,仅作为底层理论模型。

5. 异步 IO(Asynchronous IO,AIO)

  • 通俗比喻:你点完奶茶后直接回家,店员做好后亲自把奶茶送到你家(全程无需你参与等待 / 取货)。
  • 核心逻辑:
    • 应用程序发起 IO 请求后,立即返回,内核会完成「等待数据 + 拷贝数据」的全流程;
    • 当整个 IO 过程(数据拷贝到用户缓冲区)完成后,内核通过回调 / 通知的方式告知应用程序。
     
  • Java AIO(NIO.2)示例:
    java
    import java.nio.channels.AsynchronousServerSocketChannel;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.nio.channels.CompletionHandler;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;// AIO服务端:异步处理连接和数据读取
    public class AIOExample {public static void main(String[] args) throws Exception {// 1. 创建异步服务端通道AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open();serverChannel.bind(new InetSocketAddress(8080));System.out.println("AIO服务端启动,等待连接...");// 2. 异步接受连接(非阻塞,完成后回调)serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {@Overridepublic void completed(AsynchronousSocketChannel clientChannel, Object attachment) {// 继续接受下一个连接(否则只能处理一个连接)serverChannel.accept(null, this);// 3. 异步读取数据(完成后回调)ByteBuffer buf = ByteBuffer.allocate(1024);clientChannel.read(buf, buf, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer len, ByteBuffer buffer) {if (len > 0) {buffer.flip();System.out.println("收到数据:" + new String(buffer.array(), 0, len));}try {clientChannel.close();} catch (Exception e) {e.printStackTrace();}}@Overridepublic void failed(Throwable exc, ByteBuffer buffer) {exc.printStackTrace();}});}@Overridepublic void failed(Throwable exc, Object attachment) {exc.printStackTrace();}});// 主线程不退出Thread.sleep(Integer.MAX_VALUE);}
    }
  • 特点:全异步、无阻塞,性能最高,但实现复杂,需要操作系统底层支持(Linux 下 AIO 支持有限)。
  • 适用场景:高并发、大文件传输、低延迟的场景(如分布式存储、高性能中间件)。

二、核心对比表(快速记忆)

 
IO 模型等待数据阶段拷贝数据阶段核心特点Java 实现
阻塞 IO(BIO) 阻塞 阻塞 简单但性能差 Socket、ServerSocket
非阻塞 IO(NIO) 非阻塞(轮询) 阻塞 减少等待,但 CPU 开销大 Java NIO(非 Selector)
IO 多路复用 阻塞(复用器) 阻塞 一个线程管理多通道,高效 Java NIO Selector
信号驱动 IO 非阻塞(信号) 阻塞 无需轮询,实现复杂 无直接 Java API
异步 IO(AIO) 非阻塞 非阻塞 全异步,性能最高 Java NIO.2(AIO)
 

总结

  1. 基础核心:IO 模型的核心差异在于「等待数据」和「拷贝数据」两个阶段是否阻塞;
  2. 实战重点:日常开发中,BIO 用于简单场景,NIO(多路复用)是高并发主流(如 Netty),AIO 适用于超高性能需求场景;
  3. Java 视角:Java 中的 NIO≠非阻塞 IO,而是「IO 多路复用」,AIO 才是真正的异步 IO,且 Netty 虽基于 NIO,但通过封装实现了接近 AIO 的异步体验。
http://www.jsqmd.com/news/298881/

相关文章:

  • 01-移植NXP官方的U-Boot
  • 让opencode+GLM-4.7+SKILL一起服务
  • CSS-选择器
  • 整理2026年淮南艺体高考培训学院排名,合肥东辰职业学校性价比高
  • 讲讲高质量铸造钢球特点,山东金池重工产品有哪些功能亮点?
  • 2026年十大靠谱的PVC塑胶地板供应商排名,新凯琳实力入围
  • 武汉德语培训公司哪家口碑好
  • 2026沐浴露专业品牌推荐,恋香花语精准护理产品值得拥有
  • 【第1章·第12节】MATLAB/C语言混合编程应用2——通过PSO粒子群算法实现网络节点最大覆盖率优化
  • 2025年国内知名的花灯加工厂排行榜单,庙会花灯/演绎花灯/马年花灯/大型花灯/传统花灯/春节国潮花灯,花灯定制厂家推荐
  • 2026.1.23 闲话:TopTree 维护仙人掌
  • C++趣味找错误,请找出这个C++程序到底有多少错误!
  • 市场评价高的流化床干燥机厂家,定制服务解析,干燥设备/干燥机/闪蒸干燥机/喷雾干燥机/废液干燥系统,干燥机批发厂家排行榜
  • 聊聊口碑好的电火花加工,汉霸数控为何受众多知名企业信赖?
  • 2025年成都火锅品牌排行,这10家回头客最多!美食/烧菜火锅/火锅/特色美食/社区火锅成都火锅品牌推荐榜单
  • 心灵的三重疆域:弗洛伊德意识三层结构理论解析
  • 43578344
  • 8768756
  • 靠谱的安全阀在线检测仪加工厂技术对比,江西选哪家好?
  • 2026年推荐一下优质的PVC运动地板制造商,新凯琳
  • 揭秘靠谱的金属带材电镀厂家排名,鼎亚电子上榜了吗?
  • SAM exSAM 学习笔记
  • Matlab去除CT扫描图像环形伪影的实现方法
  • 《把脉行业与技术趋势》-100-电动机——永不落幕的能源转换艺术
  • 麻省理工学院人工智能领域有影响力人物
  • 幽冥大陆(一百11)酒店智能门锁系统Larkdll接口函数——东方仙盟筑基期
  • 未来之窗昭和仙君(六十三)可编程子窗口操作功能—东方仙盟练气期
  • 基于开源AI大模型S2B2C商城系统的无人店铺售卖难点解决方案研究
  • Linux驱动学习笔记:spi-imx.c收发消息的核心流程
  • 内核日志分析:__spi_pump_messages的Caller_Optimization和KWorker_Thread