一、Buffer梳理
1.1 字段解释
表中几个字段的数学关系是:0 <= mark <= positon <= limit <= capacity
| 字段名 |
说明 |
备注 |
capacity |
buffer容量 |
比如在ByteBuffer.allocate(1024)表示将容量设置为1024 |
position |
当前指针偏移量 |
比如在新创建的byteBuffer中put()一个byte,此时position由0变为1 |
limit |
限制指针的大小 |
比如ByteBuffer.allocate(1024)此时limit为1024,所以position最大为1024。 |
mark |
临时标记,默认是未定义的 |
假设IntBuffer.allocate(1024),现在position位置为10,现在只想发送512到1024之间的缓冲数据,此时我们可以buffer.mark(buffer.position())既将position记入mark位置,然后buffer.postion(512),此时发送的数据就是512到1024之间的数据。发送完成后,调用buffer.reset()将mark临时标记赋值给position使得position=mark。注意如果未设定mark,而调用了buffer.reset()方法则会抛出InvalidMarkException |
1.2 方法汇总
| 方法 |
说明 |
备注 |
capacity() |
获取容量大小 |
|
position() |
获取当前值的偏移量 |
|
position(int newPosition) |
设置偏移量指针未知 |
newPosition需要小于capacity |
limit() |
获取当前limit大小 |
|
limit(int newLimit) |
设置当前limit大小 |
limit应该小于等于capacity并大于0 |
mark() |
记录当前的偏移量位置 |
即 mark=position |
reset() |
重置为先前偏移量的位置 |
本方法一般要和mark()方法配合使用,当没有初始化mark()值会抛出InvalidMarkException异常 |
clear() |
清除缓冲区 |
将position=0,limit=capacity,mark=-1 |
flip() |
读写翻转 |
将limit=position,position=0,mark=-1。需要注意假设一个position=1,capacity=1024的读状态的buffer翻转此时limit=1而不是1024 |
rewind() |
回退缓冲区 |
他只是将position=0和mark=-1 |
remaining() |
返回当前位置和limit之前的元素数 |
|
hasRemaining() |
判断当前位置和limit之前是否还存在元素 |
二、Channel梳理
1.1 基本介绍
channel可以同时进行读写而流只能读或者写
channel可以从buffer中读数据,也可以向buffer中写数据
常用的 Channel 类有:FileChannel、DatagramChannel、ServerSocketChannel、SocketChannel、ServerSocketChannel、SocketChannel
三、Selector梳理
3.1 基本介绍
- Java 的 NIO,用非阻塞的 IO 方式。可以用一个线程,处理多个的客户端连接,就会使用到Selector(选择器)
- Selector 能够检测多个注册的通道上是否有事件发生(注意:多个Channel以事件的方式可以注册到同一个Selector),如果有事件发生,便获取事件然后针对每个事件进行相应的处理。这样就可以只用一个单线程去管理多个通道,也就是管理多个连接和请求。
- 只有在 连接/通道 真正有读写事件发生时,才会进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程,不用去维护多个线程4) 避免了多线程之间的上下文切换导致的开销
3.2 方法汇总
| 方法名 |
说明 |
备注 |
| open() |
创建一个selector |
|
| isOpen() |
判断当前selector是否开启 |
|
| keys() |
返回当前selector注册的所有channel的selectionKey |
|
| selectedKeys() |
返回当前selector中等待io操作的channel的selectionKey |
|
| selectNow() |
通过非阻塞的方式获取当前等待io的channel的键数量 |
|
| select() |
通过阻塞的方式获取当前等待io的channel的键数量 |
|
| select(long timeout) |
同上,只不过多了一个等待超时时间 |
|
| wakeup() |
唤醒阻塞的select() |
调用wakeup()没有select操作,下次调用select相关操作立即返回,不执行poll(),包括selectNow()。多次调用与一次效果一样 |