您的位置:首页 > 编程语言 > Java开发

java nio 学习笔记2

2013-08-12 22:42 183 查看
直接缓冲区和非直接缓冲区

这里主要想讲讲直接和非直接缓冲区的区别

1.简单介绍

直接缓冲区:在jvm中,字节数组可能不会在内存数组中连续储存,而gc也有可能随时移动这个数组的内存地址。而同时在java中,数组是对象,而对象在不同的jvm中实现的存储方式个不一样,基于这个原因,就诞生了直接缓冲区这个概念,通过固有代码来告诉操作系统进行直接释放或者填充数组的操作。如果你向通道传入一个非直接缓冲区对象用于写操作,那么可能会隐含的进行一下操作:

i.生成一个临时的直接ByteBuffer缓冲区

ii.将非直接缓冲区中的内容写入第一步生成的直接缓冲区中

iii.使用临时缓冲区进行底层次的IO操作

iv.这个临时缓冲区使用完毕,被系统销毁

但是有一点,就是在创建和销毁直接缓冲区的时候开销会大大高于非直接缓冲区,也就是说如果在一个可以重复使用的地方,可以直接将缓冲区声明成直接缓冲区,这样会使效率有较大的提升。

2.生成方法:

直接缓冲区:allocateDirect(capacity)

非直接缓冲区:allocate(capacity),wrap(byte[]);

从生成方法来看,直接缓冲区只有一种方法allocateDirect(capacity),而且直接缓冲区使用duplicate(),slice(),asReadOnlyBuffer()生成的新共享缓冲区都会是直接缓冲区,同时生成的视图缓冲区也是好字节缓冲区;而非直接缓冲区有两种生成方式。

3.系统底层区别

其实直接缓冲区跟非直接缓冲区在底层的差异更多的依赖于操作系统和jvm,以及代码的结构设计,如果差异过大,那么效率也会有很大的差别。

视图缓冲区

通过ByteBuffer的asXxxBuffer()生成的XxxBuffer类型,其实从底层源代码来看,并不是直接生成的XxxBuffer因为所有XxxBuffer都是抽象类,比如ByteBuffer.allocate(capacity)生成的实际上是HeapByteBuffer,而通过asXxxBuffer生成的是ByteBufferAsXxxBufferB或者ByteBufferAsXxxBufferL(ByteBufferAsXxxBufferRL或者ByteBufferAsXxxBufferRL,R代表ReadOnly),末尾的B和L代表的是Big_Endian和Little_Endian,这两个属性是ByteOrder里面的,ByteBuffer可以通过order(ByteOrder
bo)来这是,这里暂时不解释,放到字节顺序里面去解释。

下面以CharBuffer为例,看下java底层源代码中的实现:

ByteBufferAsCharBufferL(ByteBuffer bb) {   // package-private

super(-1, 0,
bb.remaining() >> 1,
bb.remaining() >> 1);
this.bb = bb;
// enforce limit == capacity
int cap = this.capacity();
this.limit(cap);
int pos = this.position();
assert (pos <= cap);
offset = pos;
}

}


这里跟duplicate(),slice(),asReadOnlyBuffer()这三个方法会有较大的差别,生成的新缓冲区的容量只有源缓冲区remaining()获取的大小的一半(细节啊,一半是直接右移一位,要是我,肯定直接除2了,o_o),并且还有一个很大的差别是,asCharBuffer生成的新缓冲区具有原缓冲区的内容,且在原缓冲区上的修改,在新缓冲区上也可以见,这点跟之前三个方法区别很大,从源代码上讲,asCharBuffer()会生成一个新的ByteBufferAsXxxBufferXX这4个类中都包含一个ByteBuffer对象,这个对象永远保存原对象的缓冲区内容,而HeapByteBuffer中并不含有这个对象,duplicate()这三个method都是直接生成一个新的HeapByteBuffer,并把原Buffer中的position,limit,capacity传给新的buffer。

PS一下:Buffer这里的这种结构,使用的设计模式,让我在我自己的项目中突然有所顿悟,在自己的项目里,产品那块的代码实现方案应该是可以按照这种做法来尝试一下。

字节顺序

明天继续!

最后一句话:想让他运行起来,在加快他的速度。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: