一、字节缓冲区方法allocateDirect()和allocate()简介
当Java程序员在编写相应的Java应用时一般都不会用到字节,所以大家对byte字节的了解也是知之甚少,但是当我们随着工作经验的增加年限的增长想要对Java底层有更深入的了解时,这时我们发现Java底层在操作数据时都是以字节的表现形式进行操作。
jvm和操作系统操作字节时又喜欢使用缓冲区来提升效率,因此我们就会了解到Java中的这样一个类,它的名字叫ByteBuffer,实际意思是字节缓冲区。
根据jvm内存分配和内存使用机制,ByteBuffer类提供了两种创建字节缓冲区的方法,并且它们是静态方法,可以直接调用,具体语法结构如下图:
上图中的这两个静态方法一个叫allocateDirect()方法,另一个叫allocate()方法,它们都是传入一个容量参数,然后创建一个代表字节缓冲区的ByteBuffer对象。
二、二者之间的联系区别
1)相同点与联系
这两个方法之间的相同点都是操作字节的缓冲区,都是以传入的标记容量为上限为界限,新创建的缓冲区的位置都是零,并且他们的标记都是不确定的,传入的参数值必须都是正整数,如果为负数就会抛出IllegalArgumentException异常。
2)不同点与区别
它们二者之间的不同点之处就在于allocate()方法是直接在JVM内存中产生的一段字节缓冲区,另一种allocateDirect()则是是脱离了JVM内存的,它是在系统级别分配的字节缓冲区。
具体区别主要还是从Java程序的内存读取和内存分配这一点来说明,传统的allocate()方法应用的是当Java程序通过Io读写数据的时候首先会被系统内存所获取,然后系统内存再复制一块内存供Java程序所使用。
allocateDirect()方法相比第一种就高明的多,它直接省略掉系统内存复制这一块儿了,因为它是直接在系统级别分配的内存,相对而言它的效率会更高一些。
这里说的效率高是在一定条件下的,而并不是任何时候它的效率都是最高的,虽然系统级别的分配内存要少了一个步骤,但是系统分批内存比较耗时耗力,消耗资源比较大,下面是两种方法进行Io读写操作时的效率图我们可以看一下它们的效率对比。
从上图中的读写操作时间我们也可以看出,如果二者读取的字节数量级都非常小的话,其实它俩的操作效率基本是相同的,没有多大区别。
当独写的字节数量级达到一定级别后,量级非常大的时候,allocateDirect()的优势就体现出来了,它的读写操作效率会更快许多。
三、allocateDirect的适用场景
上问中讲了那么多效率的对比,我们还是有必要再谈一下allocateDirect的适用场景,这样才有便于以后在工作中应用时能够得心应手的选择这两种方法选择其一进行使用。
根据allocateDirect缓冲区分配创建机制我们可以了解到,它是与操作系统内存直接挂钩的,它能够与操作系统更兼容更能够提高io操作速度,但是它消耗的资源比较大,因此我们应该应用在那种缓冲区一旦创建就不需要销毁而需要长期一直使用并且能够不浪费经常重复使用的这种场景。
Java官方推荐当使用字节的缓冲区时,如果在操作大型文件以及生命周期很长的时候,才建议使用allocateDirect()方法,因为如果生命周期太短,我们不可能频繁的创建这种缓冲区,频繁创建对内存开销实在是太大很明显不适合,因此,需要生命周期比较长久并且能够重复使用才能够发挥它的作用。
再一个是操作大型文件时建议使用是因为这些量级太小的情况下,直接用allocate就可以了,根本显示不出allocateDirect的任何优势,以上就是其比较合理的应用场景,其它的场景建议还是使用allocate吧。