【后端面经-Java】I/O多路复用 简录

【后端面经-Java】I/O多路复用 简录

    • 0. Java 线程IO模型
    • 1. BIO
    • 2. NIO
    • 3. I/O多路复用(主要)
      • 3.1 概念
      • 3.2 实现
        • 1. select
        • 2. poll
        • 3. epoll
    • 4. AIO
    • 5. 技术对比
      • 5.1 BIO、NIO、I/O多路复用、AIO对比
      • 5.2 `select`、`poll`、`epoll`对比
    • 6. 面试模拟
    • 参考资料

0. Java 线程IO模型

Java当中的线程I/O模型如图所示:
在这里插入图片描述

1. BIO

当一个线程进行I/O操作的时候,传统的做法是阻塞等待,直到I/O操作完成再继续后续的操作,这种IO方式就是BIO(Blocking I/O)。

BIO方式的缺点是:

  • 大量并发线程的场景下效率过低;
  • 空等待浪费资源;

2. NIO

JDK1.4引入了NIO(No Blocking I/O或者是New I/O)。NIO是一种同步非阻塞的I/O模型,相对于BIO,NIO允许一个线程在I/O操作的时候处理其他任务,但是需要定期轮询检查I/O操作是否完成。
NIO的缺点在于:

  • 轮询的时间间隔不好把握;
  • 一个线程处理一个I/O操作,如果存在大量I/O,处理其他任务和轮询操作反复切换状态,上下文切换开销大;

3. I/O多路复用(主要)

3.1 概念

为了解决NIO的缺点,Linux引入了I/O多路复用的机制,即一个线程可以同时监听多个I/O操作,当某个I/O操作完成后,会通知线程进行处理。
多路指的是多个SOCKET连接之间的I/O操作,复用指的是共用一个线程。
I/O多路复用的优点在于:

  • 一个线程可以同时监听多个I/O操作,减少了线程的数量,避免了线程切换的开销;

需要注意的是,I/O多路复用只有和NIO配合使用才能发挥作用,因为NIO是非阻塞的,所以可以在一个线程中同时监听多个I/O操作,而BIO是阻塞的,一个线程只能处理一个I/O操作,所以无法实现I/O多路复用。

3.2 实现

I/O多路复用的实现思路:
对于多个socket连接,程序提供一个文件描述符集合给系统,当某个接口的I/O操作完成后,会通知线程进行处理。

实现I/O多路复用的方式有三种:selectpollepoll

1. select

函数原型如下所示:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  • nfds:文件描述符的数量,即文件描述符集合中最大的文件描述符加1;
  • readfds:读文件描述符集合;
  • writefds:写文件描述符集合;
  • exceptfds:异常文件描述符集合;
  • timeout:超时时间;

从参数可以看出来select方式监听读、写、异常事件。

select根据监听的事件类型分别创建三个文件描述符数组,然后在timeout时间内阻塞线程进行监听,直到有事件发生或者超时。之后检查数组中是否有事件到达。
select的缺点在于:

  • 文件描述符数组大小有限,为1024,因此对于高并发场景并不适用;
  • 维持三个文件描述符数组,占据大量的内存空间;
  • 每次调用select需要将数组从用户空间拷贝到内核空间,同时重新对数组进行遍历查找,效率低;

2. poll

函数原型如下所示:

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  • fds:文件描述符数组;
  • ndfs:文件描述符数组的大小;
  • timeout:超时时间;

本质的工作过程和select类似,但是稍微做了改进,只需要构建一个数组,并且数组大小不受限制,而是能够自由指定;
poll的缺点在于:

  • 每次调用poll之后都需要进行数组遍历,这一点并没有改进

3. epoll

为了解决selectpoll的缺点,在高并发场景下,不同的操作系统引入了不同的解决方案,例如Linux引入了epoll、FreeBSD引入了kqueue、Solaris引入了/dev/poll
epoll实现I/O多路复用,步骤如下:

  1. 先创建epoll对象:
int epfd = epoll_create(10);

其中,int epoll_create(int size)会在内核空间开辟一块指定大小的数据表,并由epfd指向这部分内存。
2. 创建好epoll对象之后,使用epoll_ctl将注册需要监听的事件:

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  • epfd是创建数组之后的内存指针;
  • op是操作类型,包括三种模式:
    • EPOLL_CTL_ADD:添加需要监听的事件;
    • EPOLL_CTL_MOD:修改需要监听的事件;
    • EPOLL_CTL_DEL:删除需要监听的事件;
  • fd是需要监听的文件描述符,需要支持NIO;
  • event记录了注册事件的具体信息。数据结构如下所示:
typedef union epoll_data {void    *ptr;int      fd;uint32_t u32;uint64_t u64;
} epoll_data_t;struct epoll_event {uint32_t     events;    /* Epoll events */epoll_data_t data;      /* User data variable */
};
  1. 使用epoll_wait进行监听:
    epoll_wait函数原型如下所示:
int epoll_wait(int epfd, struct epoll_event *evlist, int maxevents, int timeout);
  • epfd是创建数组之后的内存指针;
  • evlist是用于存放事件的数组,也是返回的结果数组,包含被触发事件的对应文件描述符;
    • 这里显示了和selectpoll的区别,selectpoll会返回所有文件描述符然后遍历,而epoll只会返回被触发事件的文件描述符;
  • maxevents是监听事件的最大容量;
  • timeout是超时时间;
    监听步骤是block的,也就是阻塞的,只有超时才会返回;

epoll的优点在于:

  • 只返回触发事件的文件描述符,避免了整个数组的遍历;
  • 支持水平触发(Level Trigger)和边缘触发(Edge Trigger)两种模式;
    • 对于水平触发和边缘触发,具体解释可参考这篇博客;

4. AIO

AIO(Asynchronous I/O),即异步非阻塞I/O模型,AIO的实现方式是基于事件和回调机制的,当一个I/O操作完成后,会通知线程进行处理,因此不需要轮询操作。

AIO和NIO的区别在于:

  • NIO:线程需要定时检查I/O操作是否完成;
  • AIO:安心去做其他事情,等到通知之后才会进行处理;

5. 技术对比

5.1 BIO、NIO、I/O多路复用、AIO对比

在这里插入图片描述

5.2 selectpollepoll对比

在这里插入图片描述

6. 面试模拟

Q:IO多路复用是什么意思?
A:IO多路复用指的是一个线程管理多个IO连接,监听多个IO事件;

Q:NIO的具体含义
A:NIO一般理解为Not Blocking IO,即非阻塞IO,和传统的BIO(阻塞IO)相比,NIO模型中,一个线程在IO操作的时候可以处理其他任务,定期轮询检查IO操作是否完成

Q:基于什么实现的I/O多路复用?
A:传统的实现方式包括selectpoll,但是这两类方法都需要遍历数组,效率较低,为此不同的操作系统提出了不同的改进方案,例如solaris提出了/dev/poll,FreeBSD提出了kqueue,Linux提出了epoll,而epoll相比于selectpoll的主要区别就是返回的事件列表只包括触发事件的文件描述符,而不是全部监听事件的文件描述符,改进了数组遍历这一监听方式。

参考资料

  1. 一文彻底理解Java IO模型(阻塞IO非阻塞IO/IO多路复用)
  2. IO多路复用机制详解
  3. 讲讲BIO和NIO以及IO多路复用

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我国新能源汽车存量已突破1620万辆,登记数量创历史新高

根据公安部发布的最新数据,截至2023年6月底,全国的机动车数量达到4.26亿辆,其中汽车数量为3.28亿辆,新能源汽车数量为1620万辆。与此同时,机动车驾驶人口达到5.13亿人,其中汽车驾驶人口为4.75亿人。在2023年…

从C语言到C++_25(树的十道OJ题)力扣:606+102+107+236+426+105+106+144+94+145

目录 606. 根据二叉树创建字符串 - 力扣(LeetCode) 解析代码: 102. 二叉树的层序遍历 - 力扣(LeetCode) 解析代码: 107. 二叉树的层序遍历 II - 力扣(LeetCode) 解析代码&…

Microsoft 宣布今年底关闭开源软件托管平台 CodePlex

Microsoft 宣布,将关闭开源软件托管平台 CodePlex。Microsoft 2006 年推出这项服务,并决定在今年 12 月 15 日将其关闭。 Microsoft 公司副总裁 Brian Harry 在网上博客中写道,人们将可以下载他们的数据档案,Microsoft 正与面向开…

CMake之CPack

文章目录 一、CPack1.用CPack打包成为deb包2.如何确定的Depends依赖包?3.如何确定编译Build-Depends?4.Cpakc打包RPM包 二、deb的简单使用三、deb包相关文件说明1.control文件2.preinst文件3.postinst文件4.prerm文件5.postrm文件 一、CPack CPack 是 CMake 2.4.2…

(转载)支持向量机(SVM)的回归拟合(matlab实现)

与传统的神经网络相比,SVM具有以下几个优点: (1)SVM是专门针对小样本问题而提出的,可以在有限样本的情况下获得最优解。 (2)SVM算法最终将转化为一个二次规划问题,从理论上讲可以得到全局最优解,从而解决了传统神经网…

linux 信号原理 信号处理设置signal, 信号发送kill,信号等待sigsuspend,信号阻塞sigprocmask,一网打尽信号使用

​专栏内容: postgresql内核源码分析 手写数据库toadb 并发编程 个人主页:我的主页 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 概述 信号是一种软中断的方式,让进程陷入中断处理调…

集成支付宝报错订单信息有错误,建议联系实家。 错误码: TOTAL FEE EXCEED

问题 集成支付宝报错——订单信息有错误,建议联系实家。 错误码: TOTAL FEE EXCEED 详细问题 笔者按照支付宝沙箱支付快速集成版进行操作,操作完成访问所集成的支付宝,页面如下 发起请求核心代码 response.sendRedirect("http://ip…

HCIA-HarmonyOS Application Developer学习笔记

目录 一、HarmonyOS 介绍二、HarmonyOS 应用开发流程HarmonyOS 系统架构HarmonyOS 子系统集DevEco StudioHarmonyOS 应用包结构使用资源文件的方法权限管理分布式能力 三、Ability 设计与开发Ability 的概念和分类页面生命周期Intent载体页面间导航Particle Ability 开发 四、U…

Java 动态规划 Licode面试题 08.01. 三步问题

代码展示&#xff1a; class Solution {int mod(int)1e97;public int waysToStep(int n) {//特殊情况处理if(n1||n2){return n;}if(n3){return 4;}//定义dp数组int[]dpnew int[n1];//初始化dp[1]1;dp[2]2;dp[3]4;for(int i4;i<n;i){dp[i]((dp[i-1]dp[i-2])%moddp[i-3])%mod…

git安装及初步使用

git的安装 &#xff1a; 在CentOS 7.6环境下可以使用一条语句就能安装git yum -y install git如果上面命令包以下错误&#xff0c;说明权限不够 [leijiefl ~]$ yum -y install git Loaded plugins: fastestmirror You need to be root to perform this command.可以转换成ro…

关于微服务治理的一些理解

关于微服务治理的一些理解 微服务架构存在的意义 根本意义 其主要目的还是为了解耦&#xff0c;提高灵活性和可扩展性&#xff01; 参考&#xff1a;https://zhuanlan.zhihu.com/p/462078779 相比单体 单体架构的性能高于微服务架构&#xff0c;微服务的负载能力低于单体架构…

【uniapp开发小程序】实现点击跳转手机通话 拨打电话功能

效果图&#xff1a; 代码展示&#xff1a; <template><view class"page-map"><view class"btn" click"telFun()" style"text-align: center;">电话咨询</view></view> </template> <script&g…