从操作系统内核看Java非阻塞IO事件检测
非阻塞服务器模型最重要的一个特点是,在调用读取或写入接口后立即返回,而不会进入阻塞状态。在探讨单线程非阻塞IO模型前必须要先了解非阻塞情况下Socket事件的检测机制,因为对于非阻塞模式最重要的事情是检测哪些连接有感兴趣的事件发生,一般会有如下三种检测方式。
应用程序遍历socket检测
如图所示,当多个客户端向服务器请求时,服务器端会保存一个socket连接列表,应用层线程对socket列表进行轮询尝试读取或写入。对于读取操作,如果成功读取到若干数据则对读取到的数据进行处理,读取失败则下个循环再继续尝试;对于写入操作,先尝试将数据写入指定的某个socket,写入失败则下个循环再继续尝试。
这样看来,不管多少个socket连接都可以被一条线程管理起来,一条线程负责遍历这些socket列表,不断地尝试读取或写入数据,很好地利用了阻塞的时间,处理能力得到提升。但这种模型需要在应用程序中遍历所有的socket列表,同时需要处理数据的拼接,连接空闲时可能也会占用较多CPU资源,不适合实际使用。对此改进是使用事件驱动的非阻塞方式。
内核遍历socket的事件检测
这种方式将socket的遍历工作交给了操作系统内核,对socket遍历的结果组织成一系列的事件列表并返回应用层处理。对于应用层,他们需要处理的对象就是这些事件,这就是其中一种事件驱动的非阻塞方式的实现。
如图所示,服务器端有多个客户端连接,应用层向内核请求读写事件列表。内核遍历所有socket并生成对应的可读列表readList和可写列表writeList,readList标明了每个socket是否可读,例如socket1的值为1,表示可读,socket2的值为0,表示不可读。writeList则标明了每个socket是否可写。应用层遍历读写事件列表readList和writeList,做相应的读写操作。
内核遍历socket的方式已经不用在应用层对所有socket进行遍历,将遍历工作下移到内核层,这种方式有助于提高检测效率。但是它需要将所有连接的可读事件列表和可写事件列表传到应用层,假如socket连接数量大起来的话,列表从内核复制到应用层也是不小的开销。另外,当活跃连接较少时,内核与应用层之间存在很多无效的数据拷贝,因为它是将活跃和不活跃的连接状态都拷贝到应用层了。
内核基于回调的事件检测
通过遍历的方式检测socket是否可读可写是一种效率比较低的方式,不管是在应用层遍历还是在内核遍历。所以需要另外一种机制来优化遍历的方式,那就是回调函数。内核中socket都对应一个回调函数,当客户端往socket发送数据时,内核从网卡接收数据后就会调回调函数将此socket作为可读事件加入到事件列表中。应用层获取此事件列表即可得到所有感兴趣的事件。
如图所示,服务器端有多个客户端socket连接,首先应用层告诉内核每个socket感兴趣的事件;接着当客户端发送数据过来时,对应会有一个回调函数,内核从网卡复制数据成功后即调回调函数将socket1作为可读事件event1加入到事件列表,同样地,内核发现网卡可写时就将socket2作为可写事件event2添加到事件列表中;最后,应用层向内核请求读写事件列表,内核将包含了event1和event2的事件列表返回应用层,应用层通过遍历事件列表得知socket1有数据待读取,于是进行读操作,而socket2则可以写入数据。
这种方式由操作系统内核维护客户端的所有连接并通过回调函数不断更新可读可写事件列表,而应用层线程只要遍历这些事件列表即可知道可读取或可写入的连接,进而对这些连接进行读写操作。极大提高了检测效率,自然处理能力也更强。
上面介绍了三种非阻塞的事件检测机制,对于Java来说,非阻塞IO的实现完全是基于操作系统内核的非阻塞IO,它将操作系统的非阻塞IO的差异屏蔽了并提供统一的API,让我们不必关心操作系统。JDK会帮我们选择非阻塞IO的实现方式,例如对于Linux系统,在支持epoll的情况下JDK会优先选择用epoll实现Java的非阻塞IO。这种非阻塞方式的事件检测机制就是效率最高的“内核基于回调的事件检测”。
从操作系统内核看Java非阻塞IO事件检测的更多相关文章
- Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO
Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...
- java非阻塞IO(NIO)流程
单线程 多线程(Netty/Mina)
- 谈谈对不同I/O模型的理解 (阻塞/非阻塞IO,同步/异步IO)
一.关于I/O模型的问题 最近通过对ucore操作系统的学习,让我打开了操作系统内核这一黑盒子,与之前所学知识结合起来,解答了长久以来困扰我的关于I/O的一些问题. 1. 为什么redis能以单工作线 ...
- 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...
- 转 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
此文章为转载,如有侵权,请联系本人.转载出处,http://blog.chinaunix.net/uid-28458801-id-4464639.html 同步(synchronous) IO和异步( ...
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)
IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...
- 阻塞IO、非阻塞IO的区别
1.类与类之间的关系:依赖,实现,泛化(继承),关联,组合,聚合. 1)依赖(虚线):一个类是 另一个类的函数参数 或者 函数返回值. 2)实现(实线加小圆):对纯虚函数类(抽象类)的实现. 3)继承 ...
- 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
- 非阻塞IO模式原理
与阻塞模式对应的另一种模式叫非阻塞IO模式,在整个通信过程中读和写操作不会阻塞,当前处理线程不存在阻塞情况.从A机器到B机器它的通信过程是:A机器一条线程将通道设置为写事件后往下执行,而另外一条线程遍 ...
随机推荐
- [NOIp 2017]逛公园
Description 策策同学特别喜欢逛公园.公园可以看成一张$N$个点$M$条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,$N$号点是公园的出口,每条边有一个非负权值, 代表策策经 ...
- clique
[题目描述]数轴上有 n 个点,第 i 个点的坐标为 xi,权值为 wi.两个点 i,j 之间存在一条边当且仅当 abs(xi-xj)>=wi+wj.你需要求出这张图的最大团的点数.(团就是两两 ...
- Codeforces Round #411 (Div. 1) D. Expected diameter of a tree
题目大意:给出一个森林,每次询问给出u,v,问从u所在连通块中随机选出一个点与v所在连通块中随机选出一个点相连,连出的树的直径期望(不是树输出-1).(n,q<=10^5) 解法:预处理出各连通 ...
- ●BZOJ 2209 [Jsoi2011]括号序列
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2209 题解: Splay 很好的题,但是把智障的我给恶心到了... 首先不难发现,最后没 ...
- Unix系统的文件目录项的内容是什么,这样处理的好处是什么?
(Unix系统采用树型目录结构,而且目录中带有交叉勾链.每个目录表称为一个目录文件.一个目录文件是由目录项组成的.) 每个目录项包含16个字节,一个辅存磁盘块(512B)包含32个目录项.在目录项中, ...
- mysql免安装版下载及配置教程
第一步:下载 下载地址:http://dev.mysql.com/downloads/mysql/ 滚动到下方就能看到了,根据自己的需求下载: 我的电脑为64为的所以下载的为 Windows (x86 ...
- RHEL 7修改ssh默认端口号
RHEL7修改默认端口号(默认port22)初次安装系统完毕后默认情况下系统已经启动了sshd服务当然我们也可以先进行检查: 步骤1,检查是否已安装ssh服务 步骤2,检查服务是否已开启 如上图所示显 ...
- intellij配置hibernate自动生成hbm.xml文件
1.首先创建一个Java web项目,这里因为已经在整个项目中配置好tomcat了,所以我是直接创建module的,其实和创建project的配置方法一样,创建的时候选择Web Application ...
- OkHTTPClient
一,OKHttp介绍 okhttp是一个第三方类库,用于android中请求网络. 这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和Leak ...
- angular.run和angular.config的区别
ng的运行机制: config阶段是给了ng上下文一个针对constant与provider修改其内部属性的一个阶段 而run阶段是在config之后的在运行独立的代码块,通常写法runBlock 简 ...