在Java中当我们要对数据进行更底层的操作时,一般是操作数据的字节(byte)形式,这时经常会用到ByteBuffer这样一个类。

ByteBuffer提供了两种静态实例方式:

  1. public static ByteBuffer allocate(int capacity)
  2. public static ByteBuffer allocateDirect(int capacity)

为什么要提供两种方式呢?这与Java的内存使用机制有关。

第一种分配方式产生的内存开销是在JVM中的,而另外一种的分配方式产生的开销在JVM之外,也就是系统级的内存分配。

当Java程序接收到外部传来的数据时,首先是被系统内存所获取,然后在由系统内存复制复制到JVM内存中供Java程序使用。

所以在另外一种分配方式中,能够省去复制这一步操作,效率上会有所提高。可是系统级内存的分配比起JVM内存的分配要耗时得多,所以并非不论什么时候allocateDirect的操作效率都是最高的。

以下是一个不同容量情况下两种分配方式的操作时间对照:

由图能够看出,当操作数据量非常小时,两种分配方式操作使用时间基本是同样的,第一种方式有时可能会更快,可是当数据量非常大时,另外一种方式会远远大于第一种的分配方式。

其中allocateDirect分配的字节缓冲区用中文叫做直接缓冲区(DirectByteBuffer),用allocate分配的ByteBuffer叫做堆字节缓冲区(HeapByteBuffer)..

其实根据类名就可以看出,HeapByteBuffer所创建的字节缓冲区就是在jvm堆中的,即内部所维护的java字节数组。

而DirectByteBuffer是直接操作操作系统本地代码创建的内存缓冲数组(c、c++的数组)。

由于DirectByteBuffer操作的缓冲区是通过操作系统本地代码创建的,对于java来说创建和销毁DirectByteBuffer更消耗性能。

而HeapByteBuffer内部是直接创建的java数组,对于java来说更快。

可以根据下面的测试代码测试:

github源码地址

package NIO_FileChannel;

import java.nio.ByteBuffer;

public class DirectAndHeapSpeedCompare {

    public static void main(String[] args) {
directAndHeapSpeedCompare();
} private static void directAndHeapSpeedCompare() {
int length = 10000;
heapExecuteTime(length);
directExecuteTime(length);
} private static void directExecuteTime(int length) {
long startTime = System.currentTimeMillis();
ByteBuffer[] byteBufferArray = new ByteBuffer[length];
for (int i = 0; i < length; i++) {
byteBufferArray[i] = ByteBuffer.allocateDirect(1024);
}
long endTime = System.currentTimeMillis();
System.out.println("创建" + length + "个DirectByteBuffer所消耗的时间:" + (endTime - startTime));
} private static void heapExecuteTime(int length) {
long startTime = System.currentTimeMillis();
ByteBuffer[] byteBufferArray = new ByteBuffer[length];
for (int i = 0; i < length; i++) {
byteBufferArray[i] = ByteBuffer.allocate(1024);
}
long endTime = System.currentTimeMillis();
System.out.println("创建" + length + "个HeapByteBuffer所消耗的时间:" + (endTime - startTime));
}
}

   

创建10000个HeapByteBuffer所消耗的时间:12
创建10000个DirectByteBuffer所消耗的时间:17

  

那么为什么创建DirectByteBuffer比HeapByteBuffer性能差却还使用DirectByteBuffer呢?

答:创建DirectByteBuffer的确不如HeapByteBuffer快,但是本地IO(从操作系统本地获取数据,比如文件、socket网络数据)修改数据DirectByteBuffer是更快的。

因为:

HeapByteBuffer的缓冲区是java中的java数组,使用HeapByteBuffer读取一个文件,操作系统会先把文件读取到操作系统管理的内存中。

然后在把操作系统管理的这块内存的数据复制到jvm管理的内存(即HeapByteBuffer管理的java字节数组)中,然后HeapByteBuffer对java字节数组进行操作。。

而DirectByteBuffer

(1)先在操作系统内核所管理的内存缓冲区中(文件系统页)开辟一块内存空间(作为缓冲区),文件数据可以直接从操作系统复制到该缓冲区中

(2)用户写入和读取数据就可以直接操作这块缓冲区。。。。比使用HeapByteBuffer少了一个步骤,效率自然提升了。

什么情况下使用DirectByteBuffer(ByteBuffer.allocateDirect(int))?

1、频繁的native IO,即缓冲区 中转 从操作系统获取的文件数据、或者使用缓冲区中转网络数据等

2、不需要经常创建和销毁DirectByteBuffer对象

3、经常复用DirectByteBuffer对象,即经常写入数据到DirectByteBuffer中,然后flip,再读取出来,最后clear。。反复使用该DirectByteBuffer对象。

而且,DirectByteBuffer不会占用堆内存。。也就是不会受到堆大小限制,只在DirectByteBuffer对象被回收后才会释放该缓冲区。

什么情况下使用HeapByteBuffer(ByteBuffer.allocate(int))?

1、同一个HeapByteBuffer对象很少被复用,并且该对象经常是用一次就不用了,此时可以使用HeapByteBuffer,因为创建HeapByteBuffer开销比DirectByteBuffer低。

(但是!!创建所消耗时间差距只是一倍以下的差距,一般一次只会创建一个DirectByteBuffer对象反复使用,而不会创建几百个DirectByteBuffer,

所以在创建一个对象的情况下,HeapByteBuffer并没有什么优势,所以,开发中要使用ByteBuffer时,直接用DirectByteBuffer就行了)

总结:

HeapByteBuffer和DirectByteBuffer

1、HeapByteBuffer就是创建效率高,读取和写入的效率低。

2、DirectByteBuffer是创建效率低,读取和写入的效率高。

NIO ByteBuffer的allocate与allocateDirect区别(HeapByteBuffer与DirectByteBuffer的区别)的更多相关文章

  1. ByteBuffer的allocate和allocateDirect区别

    ByteBuffer的allocate和allocateDirect区别 在Java中当我们要对数据进行更底层的操作时,通常是操作数据的字节(byte)形式,这时常常会用到ByteBuffer这样一个 ...

  2. ByteBuffer的allocate和allocateDirect

    在Java中当我们要对数据进行更底层的操作时,一般是操作数据的字节(byte)形式,这时经常会用到ByteBuffer这样一个类.ByteBuffer提供了两种静态实例方式: public stati ...

  3. java nio中,HeapByteBuffer与DirectByteBuffer的区别

    HeapByteBuffer,顾名思义,是写在jvm堆上面的一个buffer,底层的本质是一个数组,用类封装维护了很多的索引(limit/position/capacity等) DirectByteB ...

  4. java.nio.ByteBuffer中的flip()、rewind()、compact()等方法的使用和区别

    java.nio.ByteBuffer 1. ByteBuffer中的参数position.limit.capacity.mark含义: position:表示当前指针的位置(下一个要操作的数据元素的 ...

  5. 一步一图带你深入剖析 JDK NIO ByteBuffer 在不同字节序下的设计与实现

    让我们来到微观世界重新认识 Netty 在前面 Netty 源码解析系列 <聊聊 Netty 那些事儿>中,笔者带领大家从宏观世界详细剖析了 Netty 的整个运转流程.从一个网络数据包在 ...

  6. Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer性能对比

    目前Java中最IO有多种文件读取的方法,本文章对比Stream,NIO ByteBuffer,NIO MappedByteBuffer的性能,让我们知道到底怎么能写出性能高的文件读取代码. pack ...

  7. HeapByteBuffer和DirectByteBuffer以及回收DirectByteBuffer

    由于HeapByteBuffer和DirectByteBuffer类都是default类型的,所以你无法字节访问到,你只能通过ByteBuffer间接访问到它,因为JVM不想让你访问到它. 分配Hea ...

  8. jQuery方法区别:click() bind() live() delegate()区别

    今天看到一篇jquery 事件的文章,自己写了个小例子,虽然2种方式都可以实现,但是不太明白,找了点资料 $("#box1").delegate("p",&qu ...

  9. JAVA基础之——三大特征、接口和抽象类区别、重载和重写区别、==和equals区别、JAVA自动装箱和拆箱

    1 java三大特征 1)封装:即class,把一类实体定义成类,该类有变量和方法. 2)继承:从已有的父类中派生出子类,子类实现父类的抽象方法. 3)多态:通过父类对象可以引用不同的子类,从而实现不 ...

随机推荐

  1. 动态样式语言less初识

    资料参考与http://lesscss.cn/ Bootstrap--(less)下载安装配置 http://lesscss.cn Less使用两种方法 (1)在客户端使用LESS--学习 编写 x. ...

  2. c++和c动态申请二维数组

    这是我面试中遇到的一道题,用c和c++分别申请一个二维数组,int **res,要求申请后的可以使用res[3][4]这一类防存方式. 这个是没有错误检查的版本. 答案: c++语言的版本 int * ...

  3. mysql dump备份 、 mysql还原操作练习

    1.备份mysql.dump 备份MySQL数据库的命令 mysqldump -h主机名 -u用户名 -p密码 数据库名字 > 备份的数据库名字.sql 例子: mysqldump -uroot ...

  4. odoo10学习笔记十七:controller

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/11189391.html 一:controller简述 odoo里面的controller相似于springM ...

  5. 《面向对象程序设计(java)》第十周学习总结

    201871010115     马北<面向对象程序设计(java)>第十周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh ...

  6. java修饰符的总结

    引言:Java的修饰符根据修饰的对象不同,分为类修饰符.方法修饰符.变量修饰符,其中每种修饰符又分为访问控制修饰符和非访问控制修饰符.访问控制存在的原因:a.让客户端程序员无法触及他们不应该触及的部分 ...

  7. 如何使用 aph-cli 搭建本地静态开发环境(server + proxy + mock)

    前提资源 1.aph系统使用说明 2.aph-cli 使用说明 ================================== 一.如何使用aph-cli简单起一个服务 1.在APH管理系统注册 ...

  8. JDOJ 1927 求逆序对

    洛谷 P1908 逆序对 洛谷传送门 JDOJ 1927: 求逆序对 JDOJ传送门 题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现 ...

  9. 使用jQuery的replaceWith()方法要注意的地方

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  10. Asp.Net Core 中的环境变量

    Asp.Net Core 中的环境变量 软件开发环境在大多数软件开发组织中,我们通常具有以下开发环境. 开发环境--Development 演示(模拟.临时)环境--Staging 生产环境-- Pr ...