BIO、NIO、AIO——丑九怪
写前面
Java语言对操作系统各种IO形式的封装,主要有这三种,BIO(同步阻塞)、NIO(同步不阻塞)和AIO(异步阻塞)。在使用时可以直接使用Java提供的API,不用关心操作系统的具体实现方式
三种IO
BIO
Java中最普通的IO。顾名思义,这中IO方式导致在通信时,在读写操作完成之前,线程会一直被阻塞,直到读写操作完成后,线程才被释放。整体结构如下:

server中有监听线程,监听是否有客户端进行连接,当有新的客户端连接时,我们创建一个业务线程去处理这个连接具体要做的事情。
这样做有缺陷:当访问量很大的时候,线程的创建和销毁会相当频繁,消耗系统资源,所以改进版本如下:

增加线程池,每次有新连接请求时,都向线程池索要线程,所有的线程由线程池进行统一管理,这样可以减少大部分线程创建和销毁的开销,
在C\S中使用这种IO,在大量并发连接的情况下,并不能满足性能需求。
NIO
Java1.4引入的功能,同步非阻塞式IO。使用新的解决方式:IO多路复用技术。NIO方式底层使用epoll实现(linux版本的JAVA下)(文末简单说明三种复用机制和epoll的四个核心函数)。NIO的三个核心组件:selector、channel、buffer。
selector:核心代码是三个native方法,本质上可以理解为两个容器,一个表示所有channel,另一个表示有待处理事件的channel
channel:在网络编程中可以简单理解为socket,可以对其进行读写操作
buffer:数据缓冲区
举个实际栗子,如图:

图中展示NIO使用时的模型,第一步先生成Server自己的ServerSocketChannel,并将其注册到selector的channels中,每当有client发出连接请求,selector会将client的socketchannel注册到channels中,当某个socketchannel有事件(比如IO事件)发生时,该socketchannel将被放入rdlist中,当前线程就会对其进行处理,处理结束后,当前线程继续对channels中的socketchannel进行监听,直到ServerSocketChannel接收到下一次连接请求或socketchannel发生了事件,再将其放入rdlist中,循环往复。
AIO
AIO比较NIO更近一步,在NIO中,socketchannel有事件发生,例如要读取数据时,需要线程自己读取、操作,然后返回,这个过程是同步的。而在AIO中更进一步,当有读事件发生时,操作系统会异步的读到buffer中,然后调用你的接口,返回异步读入buffer中的数据
总结
BIO 同步阻塞
针对磁盘文件读写IO操作来说,因为BIO用流读写文件,例如FileInputStrem,这种方式必须等待完成了这次IO才能返回。
NIO 同步非阻塞
无论多少客户端都可以接入服务端,客户端接入并不会耗费一个线程,只会创建一个连接,然后注册到selector上去,一个selector线程不断的轮询所有的socket连接,发现有事件了就通知你,然后启动一个线程处理一个请求即可,这个过程是非阻塞的。
但这个处理的过程中,你还是要先读取数据,处理,再返回的,这是个同步的过程。
AIO 异步非阻塞
当基于AIO的api去读写文件时,操作系统会帮你将数据读写到buffer中,等读写完成后, 操作系统会来回调你的接口, 告诉你操作完成。在这期间你不需要等待, 也不需要去轮询判断操作系统完成的状态,你可以去干其他的事情。
补充
select、poll、epoll
简单讲就是:select的底层是一个数组,大小为1024,策略是对数组进行遍历循环,查看数组中的channel是否有事件发生
poll底层使用的是链表,所以大小没有限制,策略同select一样,也是对链表上的节点进行遍历
epoll对poll进行优化,使用红黑树和双向链表进行存储和管理
epoll_create、epoll_ctl、epoll_event_callback、epoll_wait四个函数和eventpoll、epitem两个结构体
epoll中的核心数据结构是一个红黑树和一个双向链表
eventpoll是红黑树的根节点、同时也是双向链表的头结点
epitem是红黑树的叶子节点和双向链表的中间节点,结构如下图:

epoll_create函数用来创建eventpoll
epoll_ctl函数用来向channels中注册socketchannel,就是向红黑树中添加epitem
epoll_event_callback函数用来管理eventpoll下面的红黑树,当有事件发生时,将红黑树中的epitem放入双向链表中
epoll_wait函数用来在eventpoll对象中的双链表下"摘取"epitem并取出其包含的事件
1402

被折叠的 条评论
为什么被折叠?



