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

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: " +</
http://www.xdnf.cn/news/418.html

相关文章:

  • Warcraft Logs [Classic] [WCL] Usage Wizard <HTOC>
  • FPGA系列之DDS信号发生器设计(DE2-115开发板)
  • 睡前小故事数据集分享
  • 腾讯wxg企业微信 后端开发一面
  • [Swift]Xcode模拟器无法请求http接口问题
  • 阿里云Clickhouse 冷热数据分层存储 实战记录
  • 【图片识别改名工具】图片文件区域OCR识别并自动重命名,批量识别指定区域根据指定识别文字批量改名,基于WPF和阿里云的技术方式实现
  • 二进制裁剪命令mips-linux-gnu-strip 命令的使用
  • NoSQl注入学习
  • 【Flutter动画深度解析】性能与美学的完美平衡之道
  • 多人五子棋联机对战平台 测试报告
  • 【绘制图像轮廓】图像处理(OpenCV) -part7
  • leetcode哈希表(六)-三数相加
  • P11299 [NOISG 2021 Finals] Fraud 题解
  • PHP异常处理__Exception类
  • 实验4基于神经网络的模式识别实验
  • opencv 图像的旋转
  • linux下C++性能调优常用的工具
  • 真实波幅策略思路
  • 数据驱动增长:大数据与营销自动化的结合之道
  • 芝法酱躺平攻略(21)——kafka安装和使用
  • Chromium 134 编译指南 macOS篇:编译优化技巧(六)
  • Warcraft Logs [Classic] [WCL] BOSS ID query
  • 分析虚幻引擎编辑器中使用 TAA 或 TSR 时角色眨眼导致的眼睛模糊问题
  • 文字的力量
  • 数仓面试内容
  • 【基于Fluent+Python耦合的热管理数字孪生系统开发:新能源产品开发的硬核技术实践】
  • MCP协议用到的Node.js 和 npm npx
  • MFC文件-屏幕录像
  • 小测验——已经能利用数据集里面的相机外参调整后看到渲染图像