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并取出其包含的事件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值