IO多路复用

先说明一个问题:在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。网络编程其实就是多了一个连接的过程,常用在Netty一些框架。本文主要讲述标准输入输出NIO

一.BIO,NIO,AIO的区别

先说一些IO的模式

  • 我们发现,IO不是我们想象中那么简单。要想进行IO操作,需要发一个请求给CPU,CPU得到通知后,此时CPU就需要调用操作系统内核程序(磁盘控制器)。这就是用户态->内核态。
  • 磁盘控制器接到通知,使用DMA技术将数据放到PageCache中,再由CPU把数据从内核程序传回用户程序(buffer)。这就是内核态->用户态。
  • 关于上图的操作系统知识,如果不是清楚,请先移步操作系统,分3章讲清楚操作系统核心内容。

根据上面的模型,其实我们可以把一次IO粗略的分为2个步骤:「内核数据准备好」和「数据从内核态拷贝到用户态」

  • 同步IO:
  • 阻塞I/O 两个步骤都要等待。(BIO)
    • 适用于连接数目比较小,且固定的架构

IO多路复用

*
– 非阻塞I/O 第一个步骤无序等待,但是会一直询问内核是否准备好。(BIO的多线程版)

IO多路复用

*
– 多路复用I/O 在非阻塞的前提下优化,不会一直询问。但是多一个select期。(NIO)
+ 适用于连接数目多且连接比较短的操作(轻操作)。比如rpc框架,聊天服务器等。

IO多路复用
  • 异步I/O: 两个步骤都无需等待,询问完交给内核自动完成。(AIO)
  • 适用于连接数目多且连接比较长的操作(重操作),比如相框服务器,充分调用OS参与并发操作。

IO多路复用

多路复用的系统方法说明:一直在升级

  • select:用一个线程,接收到IO的请求,就将这些进行IO的文件描述符复制一份到内核,然后内存进行遍历,看哪个文件已经准备好数据,将准备好的文件描述符的个数返回给用户态,用户态再进行遍历,找到是哪个文件描述符的IO。有3个缺点如下
  • select 调用需要传入 fd 数组,需要拷贝一份到内核,高并发场景下这样的拷贝消耗的资源是惊人的。(可优化为不复制)
  • select 在内核层仍然是通过遍历的方式检查文件描述符的就绪状态,是个同步过程,只不过无系统调用切换上下文的开销。(内核层可优化为异步事件通知)
  • select 仅仅返回可读文件描述符的个数,具体哪个可读还是要用户自己遍历。(可优化为只返回给用户就绪的文件描述符,无需用户做无效的遍历)
  • poll:它和 select 的主要区别就是,去掉了 select 只能监听 1024 个文件描述符的限制。
  • epoll:epoll 是最终的大 boss,它解决了 select 和 poll 的一些问题。
  • 内核中保存一份文件描述符集合,无需用户每次都重新传入,只需告诉内核修改的部分即可。
  • 内核不再通过轮询的方式找到就绪的文件描述符,而是通过异步 IO 事件唤醒。
  • 内核仅会将有 IO 事件的文件描述符返回给用户,用户也无需遍历整个文件描述符集合。

这里附上一个大佬写的关于IO多路复用的动画:IO多路复用

二.NIO的组成

Channel:

  • 数据传输的双向通道,既可以用来读数据又可以用来写数据。主要实现类如下:
  • FileChannel:文件IO
  • DatagramChannel:UDP的IO
  • SocketChannel 和 ServerSocketChannel:TCP的IO

Buffer:

  • 用于和 NIO 通道进行交互。
  • Buffer 是一个顶层父类,它是一个抽象类,常用的 Buffer 的子类有:ByteBuffer、 IntBuffer、 CharBuffer、 LongBuffer、 DoubleBuffer、 FloatBuffer、ShortBuffer等
  • 下图为网络IO的一个简单图

IO多路复用

Selector:

  • 选择器 ,也可以翻译为多路复用器 。它是 Java NIO 核心组件中的一个,用于检查一个或多个 NIO Channel(通道)的状态是否处于可读、可写。如此可以实现单线程管理多个 channels,也就是可以管理多个网络链接,就可以避免线程上下文切换。一个Selector对应一个线程,

IO多路复用

三.Buffer中对应的Position, Mark, Capacity,Limit都啥?

IO多路复用
* limit:对buffer缓冲区使用的一个限制,从这个index开始就不能读取数据了。
* position:代表着数组中可以开始读写的index, 不能大于limit。
* mark:是类似路标的东西,在某个position的时候,设置一下mark,此时就可以设置一个标记
– 后续调用reset()方法可以把position复位到当时设置的那个mark上。去把position或limit调整为小于mark的值时,就丢弃这个mark,如果使用的是Direct模式创建的Buffer的话,就会减少中间缓冲直接使用DirectorBuffer来进行数据的存储。

四.Java中的IO流(BIO):

分类

  • 按照操作数据单位不同:字节流(8bit),字符流(16bit)
  • 按照数据流的流向不同:输入流,输出流
  • 按照流的角色分为:
  • 节点流:直接从数据源或目的地读写数据
  • 处理流:不直接连接到数据源或目的地,而是连接在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提 供更为强大的读写功能。

IO多路复用

实现类:

IO多路复用

寄语:我努力奔跑是为了追上那个曾经被寄予厚望的自己

Original: https://www.cnblogs.com/monkey-xuan/p/15877586.html
Author: 小猴子_X
Title: IO多路复用

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/579544/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • nginx路径匹配中斜线的研究

    互联网应用中,nginx的作用算是一个非常典型且牛逼的存在,它让分布式应用部署变得简洁高效,尤其是在反向代理的配置部署中,nginx的简单易用,功能强大,性能优越。。。 但是,因为…

    Java 2023年5月30日
    085
  • 数据结构(C++)–学习单链表时发现的一些小坑

    #include<bits stdc++.h> using namespace std; const int MaxSize = 10; template <cl…

    Java 2023年6月7日
    084
  • Java 将Excel转为UOS

    以.uos为后缀的文件,表示Uniform Office Spreadsheet文件,是一种国产的办公文件格式,该格式以统一办公格式(UOF)创建,使用XML和压缩保存电子表格。既…

    Java 2023年6月7日
    097
  • 4、多态

    多态概念(一共三点满足就行) 1、 继承 2、程序运行时将子类对象赋值给父类 3、通过父类去调用子类的方法 一、父类类型做方法的参数 <span class=”kwd”&gt…

    Java 2023年6月6日
    0106
  • 通过反射获取某个对象下的属性值,或通过父类获取

    java;collapse:true;;gutter:false; import org.slf4j.Logger; import org.slf4j.LoggerFactory;…

    Java 2023年6月6日
    083
  • Android 开创java世界(JNI Invocation API)

    在Android的世界中,由名称为app_process的C++本地应用程序(路径为:framework/base/cmds/app_process/app_main.cpp)调用…

    Java 2023年5月29日
    091
  • MyBatis-Plus联表查询的短板,终于有一款工具补齐了

    原创:微信公众号 &#x7801;&#x519C;&#x53C2;&#x4E0A;,欢迎分享,转载请保留出处。 哈喽大家好啊,我是Hydra。 my…

    Java 2023年6月5日
    0104
  • intellij idea 之 CheckStyle 代码格式校验

    posted @2016-04-06 11:52 聊聊IT那些事 阅读(1967 ) 评论() 编辑 Original: https://www.cnblogs.com/FCWOR…

    Java 2023年6月6日
    098
  • 【MC】我的世界零基础开云服务器教程

    【MC】我的世界零基础开云服务器教程 文章目录 【MC】我的世界零基础开云服务器教程 前言 一、需要用到的软件及网站 二、在本地开服务器 * 1.安装Java 2.在本地运行服务端…

    Java 2023年6月5日
    089
  • 备忘录--关于线程和IO知识

    因为自己还在出差中,没时间深入学习,最近工作里又有对一些技术的思考,所以这里记录下来,等回去有时间可以按照这个思路进行学习,这里主要起到备忘的作用。 1.线程难学难在我们没有理解操…

    Java 2023年5月30日
    058
  • 【Java8新特性】- 接口中默认方法修饰为普通方法

    Java8新特性 – 接口中默认方法修饰为普通方法 😄生命不息,写作不止🔥 继续踏上学习之路,学之分享笔记👊 总有一天我也能像各位大佬一样🏆 一个有梦有戏的人 @怒放吧…

    Java 2023年6月16日
    0102
  • EMQX 入门实战(2)–MQTT Java 客户端库使用

    Eclipse Paho Java Client 是用 Java 编写的 MQTT 客户端库(MQTT Java Client),可用于 JVM 或其他 Java 兼容平台(例如A…

    Java 2023年6月16日
    086
  • 基本的Dos命令

    ### &#x6253;&#x5F00;cmd&#x7684;&#x51E0;&#x79CD;&#x65B9;&#x5F0F…

    Java 2023年6月8日
    088
  • ucore操作系统学习(二) ucore lab2物理内存管理分析

    一、lab2物理内存管理介绍 操作系统的一个主要职责是管理硬件资源,并向应用程序提供具有良好抽象的接口来使用这些资源。 而内存作为重要的计算机硬件资源,也必然需要被操作系统统一的管…

    Java 2023年6月8日
    0122
  • VMware-ESXI上挂载U盘到某台虚拟机上

    第一步:在目标虚拟机上添加USB 控制器,右键单击目标虚拟机,选中”编辑设置”。如图 添加USB 控制器,单击”下一步” 选择控制器…

    Java 2023年5月30日
    0107
  • 排序算法(3)

    快速排序 快速排序可能是应用最广泛的算法了。快排流行的原因在于实现简单、并且适用于各种不同的输入数据,因此在一般的应用中比其他排序算法都要快很多。快排的优点在于其是原地排序,不向归…

    Java 2023年6月5日
    098
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球