NIO简介
- NIO 是面向缓冲区(或者说面向块)编程的, 因为Buffer底层本质上就是内存块。数据被读取到一个缓冲区, 稍后再被它处理, 需要时数据可在缓冲区前后移动, 从而增加了处理过程中的灵活性, 使用它可以提供非阻塞式的高伸缩性网络。
- NIO的非阻塞模式, 当使用一个线程从某通道发送请求或读取数据, 但它仅能得到目前可用的数据, 如果目前没有数据可用时, 就什么都不会获取, 而不是保持线程阻塞, 所以直至数据变的key读取之前, 该线程可用继续做其他事情。
- 非阻塞模式同理, 一个线程请求写入一些数据到某通道, 但不需要等待它完全写入, 该线程就可以去干别的事情了。
- 核心理解: 用一个线程来处理多个操作, 不用像BIO那样必须一个线程处理一个操作, 减少了cpu资源调度的损耗。
- 此外需要注意的是: HTTP2.0 使用了多路复用的技术, 做到了使用同一个连接并发处理多个请求, 而且并发请求的数量比HTTP1.1大了好几个数量级。
三大组件
Buffer(缓冲区)
- 值得注意的是没有BooleanBuffer哈
Channel(管道)
- 本身是一个接口
- 继承该接口的接口有:
- ReadableByteChannel(可读的字节数组管道)
- InterruptibleChannel(可中断的管道)
- NetworkChannel(网络管道)
- WritableByteChannel(可写的字节数组管道)
- SelChImpl(Select Change Implements?接口注释写的是一个允许转换(甚至更多)的接口, 暂时不去细看了)
- AsynchronousChannel(异步管道)
- 实现了该接口的类有:
- 继承该接口的接口有:
- 本身是一个接口
Selector(选择器)
- 本质是一个抽象类
- Selector <- AbstractSelector(抽象选择器) <- SelectorImpl(这其实还是个抽象类) <- WindowsSelectorImpl(窗口选择器实现类)
- 本质是一个抽象类
三者的关系
- 每个channel 都会对应一个Buffer
- Selector 对应一个线程, 该线程对应多个channel(管道)
- 上图表示有三个channel注册到了此selector程序
- 程序切换到哪个channel是由事件(Event)决定的
- Selector 会根据不同的事件, 在各个通道上切换
- Buffer本质上就是一个内存块, 底层有一个数组, 数据存放于其中
- 数据的读取写入是通过Buffer的, 此点与BIO有本质区别(BIO中要么是输入流, 要么是输出流, 不能双向传输)
- NIO 的Buffer可以读也可以写, 但是需要flip()方法切换
- channel 是双向的, 可以返回底层操作系统的情况, 如Linux底层的操作系统通道就是双向的