Java相关文章
- Java内存模型
- Java中String特性
- Java对象内存布局
- JVM结构
- JVM垃圾回收器
- Java19虚拟线程新特性
- Java线程生命周期与常见方法
- Java线程池笔记
- 浅谈synchronized锁原理
- 浅谈AQS原理
- ThreadLocal原理
- 浅谈双亲委派模型
IO的本质
- 操作系统分为用户空间与内核空间
- 任何io事件都分为两个过程
- 用户空间发起读写请求到内核空间,等待内核空间数据就绪
- 内核空间数据准备好拷贝到用户空间
- 等待数据就绪阶段是否发生阻塞等待可以将io时间分为阻塞io和非阻塞io
- 如果等待就绪阶段与内核数据拷贝阶段都阻塞的话为同步io,都不阻塞则为异步io
BIO
- 首先在服务端启动一个ServerSocket来监听网络请求,客户端启动Socket发起网络请求,默认情况下SeverSocket会建立一个线程来处理此请求,如果服务端没有线程可用,客户端则会阻塞等待或遭到拒绝。
- 如果要让 BIO 通信模型能够同时处理多个客户端请求,就必须使用多线程(主要原因是 socket.accept()、socket.read()、 socket.write()都是阻塞的)
NIO
- 同步非阻塞IO模型的实现
- 提供了与传统BIO模型中的Socket和ServerSocket相对应的SocketChannel和ServerSocketChannel两种不同的套接字通道实现。
- 本身想解决 BIO的并发问题,通过Reactor模式的事件驱动机制来达到Non Blocking的。当 socket 有流可读或可写入 socket 时,操作系统会相应的通知应用程序进行处理,应用再将流读取到缓冲区或写入操作系统。
- 在NIO中,基本所有的IO操作都是从Channel开始的,Channel通过Buffer(缓冲区)进行读写操作。
- 多路复用器Selector组件用于轮询一个或多个NIO Channel的状态是否处于可读、可写。通过轮询的机制就可以管理多个Channel,也就是说可以管理多个网络连接。
- 客户端与服务器之间通过channel通信,nio可以在channel进行读写操作,chandel都被注册到selector多路复用器上,selector通过一个线程轮询channel找到就绪的channel执行io
- bio面向流操作,nio面向管道,channel读写同时操作
- selector轮询出所有注册管道,然后通过SelectionKey可以取得就绪的Channel集合,从而进行后续的IO操作
- 核心组件
- Selector: 多路复⽤器,轮询检查多个 Channel 的状态,判断注册事件是否发⽣,即判断 Channel 是否处于可读或可写状态。使⽤前需要将 Channel 注册到 Selector,注册后会得到⼀个 SelectionKey,通过 SelectionKey 获取 Channel 和 Selector 相 关信息。
- Channel: 双向通道,替换了 BIO 中的 Stream 流,不能直接访问数据,要通过 Buffer 来读写数 据,也可以和其他 Channel 交互。
- Buffer: 缓冲区,本质是⼀块可读写数据的内存,⽤来简化数据读写。Buffer 三个重要属性: position 下次读写数据的位置,limit 本次读写的极限位置,capacity 最⼤容量。 flip 将写转为读,底层实现原理把 position 置 0,并把 limit 设为当前的 position 值。 clear 将读转为写模式(⽤于读完全部数据的情况,把 position 置 0,limit 设为 capacity)。 compact 将读转为写模式(⽤于存在未读数据的情况,让 position 指向未读数据的下⼀ 个)。 通道⽅向和 Buffer ⽅向相反,读数据相当于向 Buffer 写,写数据相当于从 Buffer 读。