首页 > 学院 > 开发设计 > 正文

IoBuffer

2019-11-11 02:20:10
字体:
来源:转载
供稿:网友
Mina中传输的所有二进制信息都存放在IoBuffer中,IoBuffer是对java NIO中ByteBuffer的封装(Mina2.0以前版本这个接口也是ByteBuffer),提供了更多操作二进制数据,对象的方法,并且存储空间可以自增长,用起来非常方便;简单理解,它就是个可变长度的byte数组! IoBuffer常用方法: 1. static IoBuffer allocate(int capacity,boolean useDirectBuffer) 创建IoBuffer实例,第一个参数指定初始化容量,第二个参数指定使用直接缓冲区还是Java 内存堆的缓存区,默认为false。 2.IoBuffer setAutoExpand(boolean autoExpand) 这个方法设置IoBuffer 为自动扩展容量,也就是前面所说的长度可变,那么可以看出长度可变这个特性默认是不开启的。 3. IoBuffer flip() limit=position , position=0,重置mask,为了读取做好准备,一般是结束buf操作,将buf写入输出流时调用;这个必须要调用,否则极有可能 position!=limit,导致position后面没有数据;每次写入数据到输出流时,必须确保position=limit。 4. IoBuffer clear()与IoBuffer reset() clear:limit=capacity , position=0,重置mark;它是不清空数据,但从头开始存放数据做准备—相当于覆盖老数据。 reset就是清空数据 5. int remaining()与boolean hasRemaining() 这两个方法一般是在调用了flip()后使用的,remaining()是返回 

limt-position的值!hasRemaining()则是判断当前是否有数据,返回position < limit的boolean值!

ByteBuffer

缓冲区都有4个属性:capacity、limit、position、mark,并遵循:mark <= position <= limit <= capacity,下表格是对着4个属性的解释:

属性 描述
Capacity容量,即可以容纳的最大数据量;在缓冲区创建时被设定并且不能改变
Limit表示缓冲区的当前终点,不能对缓冲区超过极限的位置进行读写操作。且极限是可以修改的
Position位置,下一个要被读或写的元素的索引,每次读写缓冲区数据时都会改变改值,为下次读写作准备
Mark标记,调用mark()来设置mark=position,再调用reset()可以让position恢复到标记的位置

重要概念
limit(), limit(10)等其中读取和设置这4个属性的方法的命名和jQuery中的val(),val(10)类似,一个负责get,一个负责set
reset()把position设置成mark的值,相当于之前做过一个标记,现在要退回到之前标记的地方
clear()position = 0;limit = capacity;mark = -1; 有点初始化的味道,但是并不影响底层byte数组的内容
flip()limit = position;position = 0;mark = -1; 翻转,也就是让flip之后的position到limit这块区域变成之前的0到position这块,翻转就是将一个处于存数据状态的缓冲区变为一个处于准备取数据的状态
rewind()把position设为0,mark设为-1,不改变limit的值
remaining()return limit - position;返回limit和position之间相对位置差
hasRemaining()return position < limit返回是否还有未读内容

IoBuffer 操作

分配一个新的Buffer

IoBuffer 是一个抽象类,所以它不能直接被实例化。分配IoBuffer,我们可以使用两种allocate()方法。

Java代码  收藏代码// Allocates a new buffer with a specific size, defining its type (direct or heap)  public static IoBuffer allocate(int capacity, boolean direct)    // Allocates a new buffer with a specific size  public static IoBuffer allocate(int capacity)  

allocate()方法是用一个或两个参数。第一种形式使用两个参数:

capacity - buffer的容量direct -buffer的类型。true 意味着得到一个direct buffer,false 意味着得到一个heap buffer

 

默认的buffer分配是由SimpleBufferAllocator 处理的。

可选的, 下面的形式也可以使用:

Java代码  收藏代码IoBuffer buffer = IoBuffer.allocate(8);  buffer.setAutoExpand(true);    buffer.putString("12345678", encoder);           // Add more to this buffer  buffer.put((byte)10);  

 按照上面的例子,如果数据的长度大于8byte的话,IoBuffe会根据情况重新分配其内置的ByteBuffer,它的容量会被加倍,它的limit会增长到String被写入时的最后position。这种行为与StringBuffer工作的方式十分类似。

注意:这种程序结构在MINA3.0时会被废弃,因为这并不是增长buffer容量的最好方式。这种方式很可能被一种类似InputStream的方式所替代,在InputStream的背后很可能是一组固定长度的ByteBuffers。

 

创建自动收缩的Buffer

为了节省内存,在有些情形下我们需要释放被额外分配的内存,IoBuffer提供了autoShrink 属性来达到此目的。如果autoShrink属性被打开,当compact()方法被调用时,IoBuffer回将部分的回收其容量,只使用四分之一或是更少的容量。如果需要手动控制收缩行为,请使用shrink()方法。

让我们实践一下:

Java代码  收藏代码IoBuffer buffer = IoBuffer.allocate(16);  buffer.setAutoShrink(true);  buffer.put((byte)1);  System.out.PRintln("Initial Buffer capacity = "+buffer.capacity());  buffer.shrink();  System.out.println("Initial Buffer capacity after shrink = "+buffer.capacity());    buffer.capacity(32);  System.out.println("Buffer capacity after incrementing capacity to 32 = "+buffer.capacity());  buffer.shrink();  System.out.println("Buffer capacity after shrink= "+buffer.capacity());  

 我们初始化分配一个容量为16的buffer,并将自动收缩设置为true。

让我们看一下输出的结果:

Java代码  收藏代码Initial Buffer capacity = 16  Initial Buffer capacity after shrink = 16  Buffer capacity after incrementing capacity to 32 = 32  Buffer capacity after shrink= 16  

 让我们分析一下输出:

初始化buffer的容量为16,因为我们使用16指定了该buffer的容量,16也就成了该buffer的最小容量调用shrink()方法后,容量仍旧为16,所以无论怎么调用紧缩方法,容量都不好小于其初始容量增加该buffer的容量至32,该buffer的容量达到32调用 shrink()方法,容量回收至16,从而剔除了冗余的容量

再次强调,这种方式是一种默认的行为,我们不需要明确指明一个buffer是否能被收缩。

 

Buffer分配

IoBufferAllocater负责分配并管理buffer,如果你希望使用你的方式精确控制分配行为,请自己实现IoBufferAllocater 接口。

MINA提供了IoBufferAllocater的两种实现,如下:

SimpleBufferAllocator (默认) - 每次创建一个新的bufferCachedBufferAllocator - 缓存buffer,使buffer在扩展时可以被重用

注意:在新版本的JVM中,使用cached IoBuffer并不能明显提高性能。

你可以自己实现IoBufferAllocator接口并在IoBuffer上调用setAllocator()方法来指定使用你的实现。


上一篇:免费馅饼 [dp]

下一篇:继承访问权限

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表