IO学习笔记
IO模型
IO模型就是说用什么样的通道进行数据的发送和接收,Java共支持3种网络编程IO模式:BIO,NIO,AIO
BIO(Blocking IO) 同步阻塞模型,一个客户端连接对应一个处理线程。
缺点: 1、IO代码里read操作是阻塞操作,如果连接不做数据读写操作会导致线程阻塞,浪费资源 2、如果线程很多,会导致服务器线程太多,压力太大
应用场景: BIO 方式适用于连接数目比较小且固定的架构, 这种方式对服务器资源要求比较高, 但程序简单易理解。
NIO(Non Blocking IO) 同步非阻塞,服务器实现模式为一个线程可以处理多个请求(连接),客户端发送的连接请求都会注册到多路复用器selector上,多路复用器轮询到连接有IO请求就进行处理,JDK1.4开始引入。
JDK1.4版本: 用linux的内核函数select()或poll()来实现,跟上面的NioServer代码类似,selector每次都会轮询所有的sockchannel看下哪个channel有读写事件,有的话就处理,没有就继续遍历(全量遍历)
JDK1.5版本: 引入了epoll基于事件响应机制来优化NIO(事件监听,操作系统注册函数回调)
NIO 有三大核心组件: Channel(通道), Buffer(缓冲区),Selector(多路复用器) 1、channel 类似于流,每个 channel 对应一个 buffer缓冲区,buffer 底层就是个数组 2、channel 会注册到 selector 上,由 selector 根据 channel 读写事件的发生将其交由某个空闲的线程处理 3、NIO 的 Buffer 和 channel 都是既可以读也可以写
select,poll,epoll方式对比:
方式 | select | poll | epoll |
---|
操作方式 | 循环遍历 | 循环遍历 | 事件监听,操作系统回调 | 底层实现 | 数组 | 链表 | 哈希表 | IO效率 | O(n) | O(n) | 有IO事件就绪系统注册函数就会回调,O(1) | 最大链接 | 有上限(默认1024) | 无上限 | 无上限 |
底层实现:
Selector.open()
socketChannel.register()
selector.select()
epollSelector调用链路:
总结: NIO整个调用流程就是Java调用了操作系统的内核函数来创建Socket,获取到Socket的文件描述符,再创建一个Selector对象,对应操作系统的Epoll描述符,将获取到的Socket连接的文件描述符的事件绑定到Selector对应的Epoll文件描述符上,进行事件的异步通知,这样就实现了使用一条线程,并且不需要太多的无效的遍历,将事件理交给了操作系统内核(操作系统中断程序实现),大大提高了效率。
|