non-blocking io 非阻塞io
三大组件:
-
Channel & Buffer: 数据的传输通道。(双向数据通道)、Buffer : 内存缓冲区。
- FileChannel : 文件传输通道
- DatagramChannel : udp 数据传输通道
- SocketChannel : tcp
- ServerSocketChannel : tcp 服务器端
- Buffer 常用 ByteBuffer
- 不同基本数据类型Buffer
-
Selector
-
传统的 : 一个 socket 对应一个线程,一个线程提供一个socket 服务
- 缺点 : 大批量连接服务器,内存就撑不住了。假如一个线程 1m,1024个连接就要 1g。
- 线程上下文切换成本高
- 只适合连接数少的场景。
-
线程池版的设计
- 复用线程去解决socket连接,阻塞模式下 : 在不超过最大线程数的情况下,比如说线程池里只有两个线程、四个socket,那么线程在处理 thread1 再处理 socket1 时 , 就不能管其他 socket 了。阻塞模式下,线程仅能处理一个socket连接,即使这个 socket 什么也不做。
- 仅适合短连接场景。
-
selector 版的设计
- selector 配合一个线程来管理多个 chnnel,获取这些channel 上发生的事件,channel 工作在非阻塞模式下,不会让线程一直等待一个channel 。适合连接数特别多、但流量低的场景。
- selector 的 select() 会阻塞 直到 channel 发生了读写就绪事件。这些事件发生,select 就会返回这些事件交给 thread 来处理。
- 如果流量高的话,还是只能大部分时间去单独处理这个信道。就回到了类似线程池的状态。
-
概念补充
线程上下文切换
调度操作只能由核心态来执行,所以在线程不断被调度获取对应的时间片这个过程实际上就是用户态与核心态不断切换的过程,如上首先由核心态进行调度指定的时间片,时间片结束之后接着切换为用户态来执行指定的线程,当执行完之后挂起保存对应线程的信息又切换为核心态进行调度再切换为用户态执行其他线程,这一切换过程指的就是上下文切换。