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

JAVA IO、BIO、NIO、AIO及零拷贝

概述

IO,常写作 I/O,是 Input/Output 的简称,是 Input/Output 的简称,即输入/输出。通常指数据在内部存储器(内存)和外部存储器(硬盘、优盘等)或其他周边设备之间的输入和输出

目前有三种 IO 共存。分别是 BIO、NIO 和 AIO。

BIO 全称 Block-IO 是一种同步且阻塞的通信模式。是一个比较传统的通信方式,模式简单,使用方便。但并发处理能力低,通信耗时,依赖网速。

Java NIO,全程 Non-Block IO ,是 Java SE 1.4 版以后,针对网络传输效能优化的新功能。是一种非阻塞同步的通信模式

Java AIO,全称 Asynchronous IO,是异步非阻塞的 IO。是一种非阻塞异步的通信模式。在 NIO 的基础上引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现

IO 基本模型

IO的类型主要分为:BIO、NIO 和 AIO,其基本模型如下

阻塞 IO 模型

阻塞 IO 模型,最传统的一种 IO 模型,即在读写数据过程中会发生阻塞现象

  • 当用户线程发出 IO 请求之后,内核会去查看数据是否就绪
    • 如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用 户线程交出 CPU
    • 数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用 户线程才解除 block 状态

典型的阻塞 IO 模型的例子为:如果数据没有就 绪,就会一直阻塞在 read 方法

data = socket.read();

非阻塞 IO 模型

非阻塞 IO 模型:当用户线程发起一个 read 操作后,并不需要等待,而是马上就得到了一个结果

  • 如果结果是一个 error 时,它就知道数据还没有准备好,于是它可以再次发送 read 操作
  • 一旦内核中的数据准备 好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。
  • 所以事实上,在非阻塞 IO 模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞 IO 不会交出 CPU,而会一直占用 CPU

典型的非阻塞 IO 模型一般如下: while 循环中需要不断地去询问内核数据是否就 绪,这样会导致 CPU 占用率非常高,因此一般情况下很少使用 while 循环这种方式来读取数据。

while(true){data = socket.read();if(data!= error){// 处理数据break;}
}

信号驱动 IO 模型

在信号驱动 IO 模型中,

  • 用户线程发起一个 IO 请求操作,会给对应的 socket 注册一个信号函数,然后用户线程会继续执行,
  • 当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用 IO 读写操作来进行实际的 IO 请求操作

异步 IO 模型

异步 IO 模型才是最理想的 IO 模型

在异步 IO 模型中,当用户线程发起 read 操作之后,立刻就可以开始去做其它的事

从内核的角度,

  • 当它收到一个 asynchronous read 之后, 它会立刻返回,说明 read 请求已经成功发起了,因此不会对用户线程产生任何 block
  • 内核会等待数据准备完成,然后将数据拷贝到用户线程
  • 当这一切都完成之后,内核会给用户线程 发送一个信号,告诉它 read 操作完成了

用户线程完全不需要实际的整个 IO 操作是如何进行的只需要先发起一个请求,当接收内核返回的成功信号时表示 IO 操作已经完成,可以直接 去使用数据了

在异步 IO 模型中,IO 操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完 成,然后发送一个信号告知用户线程操作已完成

  • 信号驱动模型中当用户线程接收到信号表示数据 已经就绪,然后需要用户线程调用 IO 函数进行实际的读写操作
  • 而在异步 IO 模型中收到信号 表示 IO 操作已经完成,不需要再在用户线程中调用 IO 函数进行实际的读写操作

注意:异步 IO 是需要操作系统的底层支持,在 Java 7 中,提供了 Asynchronous IO

BIO(Blocking I/O)

概述

以前大多数网络通信方式都是阻塞模式的,

  1. 客户端向服务器端发出请求后,客户端会一直等待(不会再做其他事情),直到服务器端返回结果或者网络出现问题
  2. 服务器端同样的,当在处理某个客户端A发来的请求时,另一个客户端B发来的请求会等待,直到服务器端的这个处理线程完成上一个处理

特点

  • 同步阻塞:线程在读写数据时被阻塞,直到操作完成。
  • 一连接一线程:每个客户端连接需独立线程处理,高并发时资源消耗大。

缺点:线程数随连接数线性增长,易导致资源耗尽(如 C10K 问题)。

关键类/接口

核心包:java.io
同步阻塞模型,所有操作会阻塞线程直到完成。
适用场景:简单文件操作、低并发网络通信。

类别类/接口用途
字节流InputStream/OutputStream字节数据的读写(如文件、网络流)。
字符流Reader/Writer字符数据的读写(支持编码转换)。
文件操作FileInputStream/FileOutputStream文件读写。
网络通信Socket/ServerSocketTCP 客户端和服务端的阻塞式通信。
缓冲流BufferedReader/BufferedWriter提升 I/O 性能的缓冲包装类。

示例

(TCP 服务端)

// 传统 BIO 模型
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {Socket socket = serverSocket.accept(); // 阻塞等待连接new Thread(() -> {try {BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));String request = in.readLine(); // 阻塞读取数据System.out.println("Received: " +</

相关文章:

  • 数据从辅存调入主存,页表中一定存在
  • LinearLayout 线性布局
  • 6.7 ChatGPT自动生成定时任务脚本:Python与Cron双方案实战指南
  • dac直通线还是aoc直通线? sfp使用
  • Shell脚本-什么时候需要定义变量
  • 【2025】Datawhale AI春训营-蛋白质预测(AI+生命科学)-Task2笔记
  • 实战交易策略 篇十六:猎豹阿杜打板交易策略
  • PHP异常处理__Exception类
  • TV主板的拆解学习
  • 实战交易策略 篇十五:东莞小文超级短线交易策略
  • @EnableAsync+@Async源码学习笔记之三
  • 详讲Linux下进程等待
  • 美信监控易:数据采集与整合的卓越之选
  • Java读取JSON文件并将其中元素转为JSON对象输出
  • Jenkins设置中文显示
  • [特殊字符] AI 大模型的 Prompt Engineering 原理:从基础到源码实践
  • 速查手册:TA-Lib 超过150种量化技术指标计算全解 - 1. Overlap Studies(重叠指标)
  • C++ 用哈希表封装unordered_set/unordered_map
  • 多线程——阻塞队列(六)
  • 红黑树模拟实现STL中的map和set---C++
  • 北京理工大学:教师宫某涉嫌师德失范,暂停其一切职务活动
  • 上海古籍书店重新开卷,在这里淘旧书获新知
  • 孙颖莎4比1击败陈幸同,与蒯曼会师澳门世界杯女单决赛
  • 一季度全社会用电量同比增长2.5%,3月增速显著回升
  • 第十个“中国航天日”活动将在沪举行:月球正面背面样品同框展出
  • 世界最大直径高铁盾构机掘进至长江江心,安全穿越刀鲚保护区