0%

Java-NIO知识点简单梳理

一、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=0mark=-1
remaining() 返回当前位置和limit之前的元素数
hasRemaining() 判断当前位置和limit之前是否还存在元素

二、Channel梳理

1.1 基本介绍

channel可以同时进行读写而流只能读或者写
channel可以从buffer中读数据,也可以向buffer中写数据
常用的 Channel 类有:FileChannelDatagramChannelServerSocketChannelSocketChannelServerSocketChannelSocketChannel

三、Selector梳理

3.1 基本介绍

  1. Java 的 NIO,用非阻塞的 IO 方式。可以用一个线程,处理多个的客户端连接,就会使用到Selector(选择器)
  2. Selector 能够检测多个注册的通道上是否有事件发生(注意:多个Channel以事件的方式可以注册到同一个Selector),如果有事件发生,便获取事件然后针对每个事件进行相应的处理。这样就可以只用一个单线程去管理多个通道,也就是管理多个连接和请求。
  3. 只有在 连接/通道 真正有读写事件发生时,才会进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程,不用去维护多个线程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()。多次调用与一次效果一样