Java NIO
时间:2018/1/20 19:03:05
参考 :
- Java网络编程 [Elliotte Rusty Harold 著 李帅 荆涛 译]
- Java NIO:Buffer、Channel 和 Selector
- 聊聊同步、异步、阻塞与非阻塞
- 聊聊Linux 五种IO模型
JAVA NIO#
IO
阻塞IO:当有IO操作时,系统一致等待直到IO操作完成。
NIO:非阻塞IO,使用选择器监听通道上的事件,当获取到通道上对应事件时再进行相应的操作。可以避免创建大量线程。
AIO:异步IO,通过 Future 或回调函数的方式进行IO操作执行完成之后的后续业务逻辑。
同步异步和阻塞非阻塞:
- 同步:关心调用结果。
- 异步:不关心调用结果。
- 阻塞:程序等待任务执行的时候不能执行其他任务。
- 非阻塞:程序等待任务执行的时候可以执行其他任务。
核心类#
Buffer#
IO操作数据读取和写入时的数据缓冲区。用于暂时存放数据。Buffer 有三个字段分别是:
capacity:缓冲区容量大小。position:当前读写位置。limit:最大读写位置,当达到。mark:做一个标记。
通过上面三个字段控制实际有效数据的区域 [position-limit]
常用的几个方法,以 IntBuffer 为例:
allocate(int size):申请容量。调用之后position = 0, capacity = limit = size。remaining():返回剩余元素的个数limit - positin。mark():设置mark为当前position。调用之后mark=position。reset():重置到标记位置。调用之后position=mark。put(int value):写入数据,写入到position指定的位置。调用之后position = position + 1。rewind():重置缓冲区。调用之后position=0, marked=-1。flip ():翻转,常用于切换读写模式。调用之后limit=position, position = 0, marked=-1。get():读取数据,读取position对应的数据。调用之后position = postion + 1。clear():清空缓冲区。调用之后position = 0, limit = capacity, mark = -1。slice():创建一个新Buffer,新Buffer和旧Buffer数据共享,但是坐标不共享,新BUffer的坐标position=0;limit=capacity=old_buffer.position, mark=-1。
Channel#
数据通道,数据的来源和数据写入的地方。
FileChannel:文件。DatagramChannel:UDP。SocketChannel:Socket客户端。ServerSocketChannel:Socket服务端。
Selector#
选择器。通过把 Channel 注册到 Selector 上,然后监听 Channel 对应的状态变化事件,实现非阻塞IO。
事件类型:
SelectionKey.OP_READ:通道中有数据可以进行读取。SelectionKey.OP_WRITE:可以往通道中写入数据。SelectionKey.OP_CONNECT:成功建立 TCP 连接。SelectionKey.OP_ACCEPT:接受 TCP 连接。
常用方法:
open():打开一个选择器。select():从注册的Channel中选择可以执行IO操作的,会一直阻塞直到至少有一个Channel被选择出来或者 selector 的wakeup 方法被调用或者当前线程被中断。selectNow():不阻塞没有可用的Channel时返回0。wakeup():唤醒等待的select方法。selectedKeys():返回选择器追踪被选择出来的SelectKey集合。