Java NIO简介
JDK1.4版本之前,Java IO类库是阻塞IO;从1.4版本开始,引进了新的异步IO库,被称为Java New IO类库,简称 Java NIO,之前阻塞的称为Old IO,简称OIO。新的异步IO库的目标是让Java支持非阻塞IO,弥补OIO同步阻塞的不足,为标准的Java代码提供了高速的,面向缓冲区的IO。
Java NIO 三个核心组件
- Channel (通道)
- Buffer(缓冲区)
- Selector(选择器)
Java NIO是属于IO多路复用模型,NIO组件提供了统一的API,为开发人员屏蔽了底层不同操作系统的差异。
NIO和OIO对比
-
OIO是面向流(Stream Oriented)的,NIO是面向缓冲区(Buffer Oriented)的。
-
OIO操作是阻塞的,NIO操作是非阻塞的。
-
OIO没有选择器(Selector)的概念,而NIO有选择器的概念。 NIO实现是基于底层的选择器的系统调用。 NIO的选择器是需要底层操作系统提供支持,而OIO不需要用到选择器。
通道(Channel)
在OIO中,同一个网络连接会关联到两个流:一个输入流(Input Stream),另外一个输出流(Ouput Stream)。通过这两个流,不断地进行输入和输出的操作。
在NIO中,同一个网络连接使用一个通道表示。所以NIO的IO操作都是从通道开始。
一个通道类似于OIO中两个流的结合体,既可以从通道读取,也可以向通道写入。
Selector选择器
是一个IO事件的查询器,通过选择器,一个线程可以查询多个通道的IO事件的就绪状态。
从开发层面即,首页把通道注册到选择器中,然后通过选择器的内部的机制。查询(select)这些注册的通道是否有已经就绪的IO事件(例如可读,可写,网络连接完成等)
一个选择器只需一个线程监控,即使用一个线程就可以通过选择器去管理多个通道,
与OIO相比,使用Selector选择器的最大优势:系统开销小,系统不必为每一个网络连接(文件描述符)创建进程/线程,从而减少系统开销。
缓冲区(Buffer)
缓冲区是面向流的OIO没有的,是NIO非阻塞的前提和基础。 通道的读取就是将数据从通道读取到缓冲区;通道的写入就是将数据从缓冲区写入到通道中。
NIO的Buffer(缓冲区)本质上是一个内存块,既可以写入数据,也可以从中读取数据。 NIO的Buffer类位于java.nio.Buffer是一个抽象类。 注意:是一个非线程安全的类
Buffers are not safe for use by multiple concurrent threads. If a buffer is to be used by more than one thread then access to the buffer should be controlled by appropriate synchronization.
Buffer类的主要子类
除了MappedByteBuffer的其他7种覆盖了能在IO种传输的所有Java的基本数据类型,MappedByteBuffer是专门用于内存映射的ByteBuffer类型。
Buffer类的主要属性
-
mark: 备忘位置,mark在被标记前是未定义的 可以将当前的positon读取位置临时存入mark中,需要时候再从mark标记恢复到position位置 调用mark()方法来设置mark=position,再调用reset()可以让position恢复到mark标记的位置 即position=mark -
positon: 当前位置,缓冲区中下一个要被读或写的元素索引 positon属性与缓冲区的读写模式有关。
- 写入模式
- 刚进入写模式,position值为0,代表写入位置从头开始
- 每当一个数据写入缓冲区之后,position会向后移动到下一个可写位置
- 初始的position值为0,最大值为limit-1。
- 读取模式 (模式切换需要使用flip翻转方法)
- 缓冲区刚开始进入到读模式,position值会被重置为0
- 从缓存区读取时,也是从position位置开始读,读取后向后移动到下一个可读位置
- position最大的值为最大可读上限limit
-
limit: 读写限制, 缓冲区中第一个不能被读或写的元素索引 limit属性在读写模式下也有不同的含义
-
写入模式 limit属性值代表可以写入的数据最大上限 在刚进入写模式时,limit的值会被设置为capacity最大容量值。 -
读取模式 切换成读模式时候,会将之前写入当前位置positon设置为读模式下limit值。 意思就切换时候把limit值设置为刚刚写到哪儿了。 -
capacity: 缓冲区的最大容量。在缓冲区创建时设定,一经设定永远不能改变
Buffer类的重要方法
? put了一个值进去,position元素位置从0变成1,limit以及capacity没变
|