Buffer
1、缓冲区类型
2、缓冲区定义
(1)Buffer是一个对象,其中包含写入与读出的数据。是新IO与原IO的重要区别。任何情况下访问NIO中的数据都需要通过缓存区进行操作。
(2)Buffer在代码中体现就是一个数组,本质上就是内存中的一块区域。
Buffer源码
???public abstract class Buffer { ???// Invariants: mark <= position <= limit <= capacity ???private int mark = -1; ???private int position = 0; ???private int limit; ???private int capacity; ???// Used only by direct buffers ???// NOTE: hoisted here for speed in JNI GetDirectBufferAddress ???long address; ???// Creates a new buffer with the given mark, position, limit, and capacity, ???// after checking invariants. ???// ???Buffer(int mark, int pos, int lim, int cap) { ??????// package-private ???????if (cap < 0) ???????????throw new IllegalArgumentException("Negative capacity: " + cap); ???????this.capacity = cap; ???????limit(lim); ???????position(pos); ???????if (mark >= 0) { ???????????if (mark > pos) ???????????????throw new IllegalArgumentException("mark > position: (" ??????????????????????????????????????????????????+ mark + " > " + pos + ")"); ???????????this.mark = mark; ???????} ???} ???????...省略}
(1)BUffer的四个属性。mark、position、limit、capacity。
[1] capacity:缓存区容量。设定即不可更改,比如 capacity 为 1024 的 IntBuffer,代表其一次可以存放 1024 个 int 类型的值。当Buffer 的容量达到 capacity,需要清空 Buffer,才能重新写入值。 ?
[2] limit:写模式是记录最大能够写入的数据。读模式下limit等于Buffer实际大小。 ?
[3] position:写模式下position初始值为0,当写入一个值时,position+1,指向下次写入位置。读模式下position会置0,这时将会从头开始读取Buffer中的数据。
[4] mark:Buffer#mark()记录当前position值,用于读写切换时还原position值。
(2)Netty提供了两个指针变量用于读写操作。分别是readerIndex与writeIndex。
+-------------------+------------------+------------------+| discardable bytes | ?readable bytes ?| ?writable bytes ?|| ??????????????????| ????(CONTENT) ???| ?????????????????|+-------------------+------------------+------------------+| ??????????????????| ?????????????????| ?????????????????|0 ?????<= ?????readerIndex ??<= ??writerIndex ???<= ???capacity
[1] readerIndex 到 writeIndex为可读度的字节缓存区。
[2] writeIndex 到 capacity为可写的字节缓存区
[3] 0 到 readerIndex为已读字节缓存区 ?
Channel
Channel定义
通道是数据来源与数据写入的目的地。主要分为以下几种,分别是FileChannel(文件通道,用于文件的读和写
)、DatagramChannel(用于 UDP 连接的接收和发送)、SocketChannel(把它理解为 TCP 连接通道,简单理解就是 TCP 客户端)、ServerSocketChannel(TCP 对应的服务端,用于监听某个端口进来的请求)
NIO Channel与Java stream区别
- 对于同一个 Channel全双工,Stream(InputStream、OutputStream)要么读要么写
- Channel 可以非阻塞的读写 IO 操作,而 Stream 只能阻塞的读写 IO 操作。
- Channel 必须配合 Buffer 使用,总是先读取到一个 Buffer 中,又或者是向一个 Buffer 写入。也就是说,我们无法绕过 Buffer ,直接向 Channel 写入数据。
为什么Netty重写Channel?
- [1]Channel是Netty的核心,为了能够与整体架构融合在一起。(待确定)
参考
[1] http://ifeve.com/java-nio-all/
多路复用器Selector
Selector会不断轮询注册在其上的Channel,当某个Channel上发生事件,该Channel就处于就绪状态,会被轮询出来进行后续IO操作。
通过一个线程(多路复用器)Selector可以同时轮询多个Channel,不必一个连接一个线程以一对一的形式应对请求,极大地减少系统开销。
当读或写事件发生时,就会从Selector中获取想用的SelectorKey,SelectionKey中可以找到发生的事件和该事件所发生的具体的SelectableChannel,以获得客户端发送过来的数据.
NIO服务端
003——Netty之Buffer、Channel以及多路复用器Selector
原文地址:https://www.cnblogs.com/boycelee/p/10014411.html