IO、NIO、BIO傻傻分不清吗,让我对象告诉你~~

news2024/11/16 18:08:01

1、Stream 与 Channel

  • stream 不会自动缓冲数据,channel 会利用系统提供的发送缓冲区、接收缓冲区(更为底层)
  • stream 仅支持阻塞 API,channel 同时支持阻塞、非阻塞 API,网络 channel 可配合 selector 实现多路复用
  • 二者均为全双工,即读写可以同时进行
  • 虽然 Stream 是单向流动的,但是它也是全双工的

2、IO 模型

  • 同步:线程自己去获取结果(一个线程)
    • 例如:线程调用一个方法后,需要等待方法返回结果
  • 异步:线程自己不去获取结果,而是由其它线程返回结果(至少两个线程)
    • 例如:线程 A 调用一个方法后,继续向下运行,运行结果由线程 B 返回

当调用一次 channel**.read** 或 stream**.read** 后,会由用户态切换至操作系统内核态来完成真正数据读取,而读取又分为两个阶段,分别为:

  • 等待数据阶段
  • 复制数据阶段

file
根据 UNIX 网络编程 - 卷 I,IO 模型主要有以下几种

阻塞 IO

file

  • 用户线程进行 read 操作时,需要等待操作系统执行实际的 read 操作,此期间用户线程是被阻塞的,无法执行其他操作

非阻塞IO

file

  • 用户线程

    在一个循环中一直调用 read 方法,若内核空间中还没有数据可读,立即返回

    • 只是在等待阶段非阻塞
  • 用户线程发现内核空间中有数据后,等待内核空间执行复制数据,待复制结束后返回结果

多路复用

file

Java 中通过 Selector 实现多路复用

  • 当没有事件是,调用 select 方法会被阻塞住
  • 一旦有一个或多个事件发生后,就会处理对应的事件,从而实现多路复用

多路复用与阻塞IO的区别

  • 阻塞 IO 模式下,若线程因 accept 事件被阻塞,发生 read 事件后,仍需等待 accept 事件执行完成后,才能去处理 read 事件
  • 多路复用模式下,一个事件发生后,若另一个事件处于阻塞状态,不会影响该事件的执行

异步IO

file

  • 线程 1 调用方法后理解返回,不会被阻塞也不需要立即获取结果
  • 当方法的运行结果出来以后,由线程 2 将结果返回给线程 1

3、零拷贝

零拷贝指的是数据无需拷贝到 JVM 内存中,同时具有以下三个优点

  • 更少的用户态与内核态的切换
  • 不利用 cpu 计算,减少 cpu 缓存伪共享
  • 零拷贝适合小文件传输

传统 IO 问题

传统的 IO 将一个文件通过 socket 写出

File f = new File("helloword/data.txt");
RandomAccessFile file = new RandomAccessFile(file, "r");

byte[] buf = new byte[(int)f.length()];
file.read(buf);

Socket socket = ...;
socket.getOutputStream().write(buf);

内部工作流如下

file

  • Java 本身并不具备 IO 读写能力,因此 read 方法调用后,要从 Java 程序的用户态切换至内核态,去调用操作系统(Kernel)的读能力,将数据读入内核缓冲区。这期间用户线程阻塞,操作系统使用 DMA(Direct Memory Access)来实现文件读,其间也不会使用 CPU

    DMA 也可以理解为硬件单元,用来解放 cpu 完成文件 IO

  • 从内核态切换回用户态,将数据从内核缓冲区读入用户缓冲区(即 byte [] buf),这期间 CPU 会参与拷贝,无法利用 DMA

  • 调用 write 方法,这时将数据从**用户缓冲区(byte [] buf)**写入 socket 缓冲区,CPU 会参与拷贝

  • 接下来要向网卡写数据,这项能力 Java 又不具备,因此又得从用户态切换至内核态,调用操作系统的写能力,使用 DMA 将 socket 缓冲区的数据写入网卡,不会使用 CPU

可以看到中间环节较多,java 的 IO 实际不是物理设备级别的读写,而是缓存的复制,底层的真正读写是操作系统来完成的

  • 用户态与内核态的切换发生了 3 次,这个操作比较重量级
  • 数据拷贝了共 4 次

NIO优化

通过 DirectByteBuf

  • ByteBuffer.allocate(10)
    • 底层对应 HeapByteBuffer,使用的还是 Java 内存
  • ByteBuffer.allocateDirect(10)
    • 底层对应 DirectByteBuffer,使用的是操作系统内存

file
大部分步骤与优化前相同,唯有一点**:Java 可以使用 DirectByteBuffer 将堆外内存映射到 JVM 内存中来直接访问使用**

  • 这块内存不受 JVM 垃圾回收的影响,因此内存地址固定,有助于 IO 读写
  • Java 中的 DirectByteBuf 对象仅维护了此内存的虚引用,内存回收分成两步
    • DirectByteBuffer 对象被垃圾回收,将虚引用加入引用队列
      • 当引用的对象 ByteBuffer 被垃圾回收以后,虚引用对象 Cleaner 就会被放入引用队列中,然后调用 Cleaner 的 clean 方法来释放直接内存
      • DirectByteBuffer 的释放底层调用的是 Unsafe 的 freeMemory 方法
    • 通过专门线程访问引用队列,根据虚引用释放堆外内存
  • 减少了一次数据拷贝,用户态与内核态的切换次数没有减少

进一步优化 1

以下两种方式都是零拷贝,即无需将数据拷贝到用户缓冲区中(JVM 内存中)

底层采用了 linux 2.1 后提供的 sendFile 方法,Java 中对应着两个 channel 调用 transferTo/transferFrom 方法拷贝数据

file

  • Java 调用 transferTo 方法后,要从 Java 程序的用户态切换至内核态,使用 DMA 将数据读入内核缓冲区,不会使用 CPU
  • 数据从内核缓冲区传输到 socket 缓冲区,CPU 会参与拷贝
  • 最后使用 DMA 将 socket 缓冲区的数据写入网卡,不会使用 CPU

这种方法下

  • 只发生了 1 次用户态与内核态的切换
  • 数据拷贝了 3 次

进一步优化 2

linux 2.4 对上述方法再次进行了优化

file

  • Java 调用 transferTo 方法后,要从 Java 程序的用户态切换至内核态,使用 DMA 将数据读入内核缓冲区,不会使用 CPU
  • 只会将一些 offset 和 length 信息拷入 socket 缓冲区,几乎无消耗
  • 使用 DMA 将 内核缓冲区的数据写入网卡,不会使用 CPU

整个过程仅只发生了 1 次用户态与内核态的切换,数据拷贝了 2 次

4、AIO

AIO 用来解决数据复制阶段的阻塞问题

  • 同步意味着,在进行读写操作时,线程需要等待结果,还是相当于闲置
  • 异步意味着,在进行读写操作时,线程不必等待结果,而是将来由操作系统来通过回调方式由另外的线程来获得结果

异步模型需要底层操作系统(Kernel)提供支持

  • Windows 系统通过 IOCP 实现了真正的异步 IO
  • Linux 系统异步 IO 在 2.6 版本引入,但其底层实现还是用多路复用模拟了异步 IO,性能没有优势

本文由传智教育博学谷教研团队发布。

如果本文对您有帮助,欢迎关注点赞;如果您有任何建议也可留言评论私信,您的支持是我坚持创作的动力。

转载请注明出处!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/140455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电商系统概要设计

设计一个最小化的电商系统,理清楚电商系统的架构。目前唯一能确定的是,老板要做一个电商系统。具体做成什么样,还不清楚。你需要和老板讨论需求。 你:“咱们要做的业务模式是C2C、B2C还是B2B呢?” 老板:“…

CES 2023:NVIDIA发力元宇宙与汽车市场

作为全球规模最大、影响最为广泛的国际消费电子展,2023年的CES(Consumer Electronics Show)在美国拉斯维加斯如约而至。众所周知,作为全球消费电子产业发展的风向标,每年的CES都汇聚了各大科技企业最先进的技术与产品。…

Renesas setting-文件导入

导入工程 1.1, 文件\从文件系统选中打开项目… 1.2, 打开xpg_app文件 链接文件 2.1,选中项目\右键\属性 2.2,删除文件(在不同电脑中绝对路径不同) 属性\路径和符号, 源位置(delete C 文件)&…

在未联网的计算机中部署 yum 源和 EPICS 环境

1. 基本背景 EPICS 软件仓库:192.168.206.234:8888 安装方式:yum 2. 配置跳板机 跳板机功能:借助ssh 隧道服务进行端口转发,使未联网的计算机能够访问软件仓库。 将未联网的计算机与一台申请了无线校园网的笔记本电脑进行有线…

PCB结构和谐振(一)

本文构建了包括不同的旋转角度、不同的叠层和两种不同布线方法(W 形和蛇形线)的测试手段,对应于这些设计的谐振是通过 VNA 测量获得的。然后,使用仿真方法来帮助我们理解这些实验结果。为了消除仿真与实验之间的差异,研…

【chatGPT】一位聊天永远秒回的朋友

目录一、chatGPT介绍二、通过猿如意体验三、在openAI官网体验2.1注册openAI2.2使用和问题说明一、chatGPT介绍 ChatGPT是由人工智能研究实验室OpenAI在2022年11月30日发布的全新聊天机器人模型,一款人工智能技术驱动的自然语言处理工具。它能够通过学习和理解人类的…

债务豁免,只是中昌数据的一次“回光返照”?

‍‍数据智能产业创新服务媒体——聚焦数智 改变商业因为经营不善,中昌大数据股份有限公司(以下简称“中昌数据”)已被实施退市风险警示,1月3日,中昌数据发布公告称收到两位债权人的《债务豁免函》,对中昌…

线程安全中的原子性,有序性和可见性

对于Java并发编程,一般来说有以下的关注点: 线程安全性,正确性。 线程的活跃性(死锁,活锁) 性能 其中线程的安全性问题是首要解决的问题,线程不安全,运行出来的结果和预期不一致,那就连基本要…

计算机的发展史与计算机硬件组成

作者简介:一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 目录 前言 一.计算机的发展史 1.计算机发展的四个时代 二.计算机硬件组成 …

#D. Journey之二

一,题目Description给出一棵树N个点及数字K接下来N-1行描述有关边的开始点,结束点.保证图中不会有环接下来K个数字,代表你要走过的点的编号.当然你可以自己选择出发点及行进的路线不一定按给定编号顺序前行,求走过的最短距离。FormatInput第一行给出N,K。…

工具及方法 - 文件正在被使用,无法改名或删除怎么办

有时我们想重命名或删除一个文件时,会提示错误,提示文件被占用。 比如提示:“The action can’t be completed because the folder is open in another program“。 或者: 或者: 就是因为有进程锁定(process is lock…

004-Ensp-实验-配置DNS

实验要求 1. 在PC2中Ping www.pc1.com 可以访问到PC2 2. 在PC1中Ping www.pc2.com 可以访问到PC2 网络结构 实验步骤 #需要开启DHCP [Huawei]interface g0/0/0 [Huawei-GigabitEthernet0/0/0]dhcp server dns-list 192.168.0.100 测试

人工智能:数字图像类型和常见格式介绍

❤️作者主页:IT技术分享社区 ❤️作者简介:大家好,我是IT技术分享社区的博主,从事C#、Java开发九年,对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉: 数据库领域优质创作者🏆&#x…

【C语言】-深入内存带你看数据的存储

🎇作者:小树苗渴望变成参天大树 🎉 作者宣言:认真写好每一篇博客 🎊作者gitee:link 如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧! 数据的存储🧨 前言✨一、数据类型…

007-Ensp-实验-配置静态路由

实验要求 PC1 可以访问到 PC2 网络结构 实验步骤 1. AR1 G0/0/0 - G0/0/1 配置IP 2. AR2 G0/0/0 - G0/0/1 配置IP 3. PC1 PC2 配置IP/GateWay 4. AR1 配置静态路由表 ip route-static 192.168.1.0 255.255.255.0 192.168.5.2 5. AR2 配置静态路由表 ip route-static 19…

Linux虚拟机克隆后网卡名从eth0变成eth1

文章目录一 系统环境二 问题发现三 解决过程一 系统环境 原本被克隆的主机是 rhel6.9 的操作系统。 二 问题发现 对 rhel6.9 的主机克隆后,发现无法SSH远程连接,从而发现可能是网卡的问题需要解决。 首先检查网卡服务是否启动 发现network服务是正常运…

java在线视频播放系统视频网站影视网站电影电视剧播放网站源码

简介 ssm开发的视频网站。本项目主要包括了视频展示和查询功能,用户中心,积分管理,管理员管理等功能。 演示视频 https://www.bilibili.com/video/BV1tT4y1N7t8/?share_sourcecopy_web&vd_sourceed0f04fbb713154db5cc611225d92156 技…

【408篇】C语言笔记-第二十二章(文件的操作)

文章目录第一节:文件操作原理1. C文件概述2. 文件指针介绍第二节:文件的打开与关闭1. 文件打开与关闭常用函数2. 代码实战第三节:文件的读写1. fread函数与fwrite函数2. fgets函数与fputs函数第四节:文件位置指针偏移1. fseek函数…

2023-01-04 clickhouse-编译、开发、测试

https://bohutang.me/2020/06/05/clickhouse-and-friends-development/ 一次偶然的机会,和ClickHouse团队做了一次线下沟通,Alexey提到ClickHouse的设计哲学: The product must solve actual problemAnd do it better than others 用工程思维解决商业问…

人工智能期末试卷

一、简答题(共 24 分) 若将人看成一个信息处理系统,1) 人的智能具有哪些特征?2) 举例说明哪一特征是最重要的并 3) 阐述其与实现通用人工智能的关系。(要求:2、3 小问一定用自己的语言作答!)(8 …