昨天的文章,大家了解了JAVA BIO的阻塞编程方式对性能有较大的影响,JDK1.4加入了新的IO特性(NIO),比较重要的是新增了高性能Buffer和非阻塞多路复用网络编程模式。
今天带大家首先对NIO有个初步的认知,带着目标读完本文:
知道了Channel和Buffer是怎么相互配合的。
大概了解Buffer的状态、属性、方法。(后续会重点说明代码上的应用)
1. 传统JAVA IO
这里总结下IO,还需要注意继承图,下面给出:
IO重点是流的概念,Stream从一个数据源中获取,不管获得Input还是Output,都是单向的。
IO实现的是装饰者设计模式,按照功能的不同,可以把Stream包装成Buffered功能的、具有Data数据类型的IO。
数据类型的转换以及Buffered的支持,都需要通过包装的形式实现,性能较低。
2. JAVA New IO
不再区分Input和Output,抽象成了Channel,是双向的,可面向文件或者Socket编程。
缓冲区和Data数据类型的转换,抽象成Buffer,例如ByteBuffer以及导出的View Buffers。
2.1 Channel
Channel的获取,主要有3个,从文件流中获取、从Socket中获取、从Pipe中获取,如下图代码
2.2 Buffers
channel负责运输通道,起到履带的作用,但是没有容器承载数据也是白搭。所有需要Buffer这个容器承载数据。Buffer有7种类型,实际上是JAVA的8种基础数据类型除去boolean类型,有:ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,Longuffer,ShortBuffer。
Buffer的属性
capacity :缓冲区能够容纳的数据元素的最大数量。
limit :缓冲区的第一个不能被读或写的元素,缓冲创建时,limit 的值等于 capacity 的值。
position :下一个要被读或写的元素的索引。缓冲创建时,position的值等于0。
所以有公式:0 <= position <= limit <= capacity
Buffer的操作
Buffer有读写两种操作,读操作有channel.read(buffer)和buffer.put(127),而写操作有channel.write(buffer)和buffer.get()。
上面的这段话很重要,务必理解清楚了。可以结合最上面的channel、buffer关系图理解
clear() :让Buffer为新一轮的读取操作做准备,设置limit的值=capacity,position=0.(为channel.read()和buffer.put()操作做准备工作)
flip() :为写操作做准备,设置limit = position,然后设置position = 0。(channel-write 或 buffer.get 操作)
rewind() :在读写模式下都可用,它单纯的将当前位置置0。一般用于复制上一次读取的数据。
Buffer的创建
要想获得一个Buffer对象首先要进行分配。 每一个Buffer类都有一个allocate方法。例如下面是一个分配1024字节的的ByteBuffer的例子。
ByteBuffer buf = ByteBuffer.allocate(1024);
分配一个可存储1024个字符的CharBuffer:
CharBuffer buf = CharBuffer.allocate(1024);
如下API
API注意:
allocate的capacity表示多个T。
asReadOnlyBuffer、duplicate、slice操作保持buffer内容不变化,但是内部属性会变化:
asReadOnlyBuffer返回只读buffer,mark、position、limit不同,改变buffer会影响此readOnly返回的Buffer
duplicate返回新的buffer和原有buffer内容相同,但mark、position、limit不同,改变buffer值会相互影响。
slice方法返回buffer剩余的内容,修改buffer相互影响。
带有index的get和put操作不影响position的位置,不带index的是相对操作,影响postion。
读完后,是否完成阅读目标,希望我写的能多少帮的到你,不足望指正。
后续会用代码让你全面理解Channel和Buffer的编程思维。
閱讀更多 吳濤分享 的文章