Java NIO 源码阅读笔记(一)

java.nio 包描述

nio作为最顶层包,定义了Buffers相关的类。
Buffers:提供了缓存数据的功能,贯穿于整个NIO API中。

NIO API的四个主要抽象包:

  1. Buffers:数据容器
  2. Charsets: 涉及到编码解码,因为序列化字符需要在Unicode编码相互转化
  3. Channels : 对应着每个IO通道,例如文件啊,网络io等等的
  4. Selectors: 和Channels结合使用

2.3.4都有自己对应的子包,我们可以通过实现子包中的结构而自定义实现

详细说下Buffers:

作为数据容器,理所当然他有一些属性与操作:

  1. 属性position:下一个将要读取数据的位置
  2. 属性limit:buffer的第一个不可读不可写的元素
  3. 操作:clear, flip, rewind, and mark/reset

最常用的就是ByteBuffers,他与其他的Buffer有特别之处:

  1. DirectBuffer:数据不受GC管理,性能更好
  2. 可以将文件一部分map到内存
  3. 以大端或小端模式读取异构或同构字节数据

抽象类Buffer

存储原始数据类型,除了boolean。

拥有:capacity,limit,position

每个实现了这个抽象类的类都有get和put操作:
相对位置操作:从position的位置开始操作,成功后改变position位置,若操作到limit则会抛出异常
绝对位置操作:通过index对数据进行操作,不会影响position的位置
注:所有的操作数据都会通过相应的channel进行传输。

mark和reset

mark是一个index,当reset出发后position所恢复的位置,mark的位置不能大于position和limit的位置。若未定义mark就调用reset就会抛出InvalidMarkException 异常。

位置关系

0 <= mark <= position <= limit <= capacity
一个初始化的buffer position是0,mark是未定义的。limit是受buffer的类型和构建时的参数决定的。

操作位置相关操作

  1. clear() limit为capacity,position为0,为从通道读数据和写数据准备
  2. flip() 将limit设置为position,position设置为0,为向通道写数据或获取数据而准备
  3. rewind() 不改变limit,将position重置为0,重新读

可读可写性

所有的buffer都是可读的,但并不是都是可写的,若写的话会抛出异常,虽然buffer内容不能改变,但是position,limit,mark是可以变得,我们可以通过isReadOnly来判断。

线程安全性

buffer不是线程安全的

最常用的ByteBuffer

因为io通常涉及网络传输和数据存储,所以数据一般都是转化为字节数据。
ByteBuffer提供六类方法:

  1. 绝对和相对的put和get 字节数据
  2. 相对位置的bulk get,将连续的字节数据读入array
  3. 相对位置的buld put,将array或者其他数据写入到buffer中
  4. 绝对和相对的put和get java类型对象,并将类型对象与字节之间转化
  5. view buffer,因为字节buffer是需要转换的,viewbuffer的意思就是将字节buffer转化为java原始类型buffer,并且内容改变会相互影响的。
  6. 提供compact,duplicating,slicing方法。compact:将position和limit之间的数据平移都buffer头部,并把postion放在数据块最后,准备继续写。duplicating和slicing相当于维护了一套position,limit,mark

direct和non-direct

一般情况下程序io写流程是:
用户缓冲区 -》 系统缓冲区 -》 磁盘
这也就是为什么linux系统总会有大量内存被cache占用的原因了。

direct IO 就是不经过系统缓冲区,直接写入磁盘。

除此之外,direct还可以直接将cache文件内容映射到用户内存区。

字节数据获取

默认通过大端方式获取存储数据,并且与java原始数据类型相互转换。
对于每个数据不等长度的读取,提供了获取和写入的方法,getFloat等。
对于每个数据同类型的buffer,可以创建view,数据之间修改具有可见性。直接返回一个已经将类型转化好了的buffer。

转化好了得view有三个好处:

  1. index不是以字节为单位的,而是以数据类型为单位
  2. 提供bulk读取写入操作
  3. byte Buffer是direct ,view buffer也是direct

此外:当view创建的时候,大小端的方式是不可修改的哦

你可能感兴趣的:(java)