一、Buffer介绍
缓冲区(Buffer)就是在内存中预留指定大小的存储空间用来对输入/输出(I/O)的数据作临时存储,这部分预留的内存空间就叫做缓冲区:
二、Buffer好处
使用缓冲区有这么两个好处:
1、减少实际的物理读写次数
2、缓冲区在创建时就被分配内存,这块内存区域一直被重用,可以减少动态分配和回收内存的次数
三、ByteBuffer字节缓冲区。
此类定义了除 boolean 之外,读写所有其他基本类型值的方法。这些基本值可以根据缓冲区的当前字节顺序与字节序列互相进行转换,并可以通过 order 方法获取和修改。特定的字节顺序由 ByteOrder 类的实例表示。字节缓冲区的初始顺序始终是 BIG_ENDIAN。
此类针对字节缓冲区定义了以下六类操作:
1)读写单个字节的绝对和相对 get 和 put 方法;
2)将此缓冲区的连续字节序列传输到数组中的相对批量 get 方法;
3)将 byte 数组或其他字节缓冲区中的连续字节序列传输到此缓冲区的相对批量 put 方法;
4)读写其他基本类型值,并按照特定的字节顺序在字节序列之间转换这些值的绝对和相对 get 和 put 方法;
5)创建视图缓冲区 的方法,这些方法允许将字节缓冲区视为包含其他基本类型值的缓冲区;
6)对字节缓冲区进行 compacting、duplicating 和 slicing 的方法。
字节缓冲区可以通过 allocation 方法创建,此方法为该缓冲区的内容分配空间,或通过 wrapping 方法将现有的 byte 数组包装到缓冲区中来创建。
四、直接与非直接缓冲区
字节缓冲区要么是直接的,要么是非直接的。如果为直接字节缓冲区,则 Java 虚拟机会尽最大努力直接在此缓冲区上执行本机 I/O 操作。也就是说,在每次调用基础操作系统的一个本机 I/O 操作之前(或之后),虚拟机都会尽量避免将缓冲区的内容复制到中间缓冲区中(或从中间缓冲区中复制内容)。
直接字节缓冲区可以通过调用此类的 allocateDirect 工厂方法来创建。此方法返回的缓冲区进行分配和取消分配所需成本通常高于非直接缓冲区。直接缓冲区的内容可以驻留在常规的垃圾回收堆之外,因此,它们对应用程序的内存需求量造成的影响可能并不明显。所以,建议将直接缓冲区主要分配给那些易受基础系统的本机 I/O 操作影响的大型、持久的缓冲区。一般情况下,最好仅在直接缓冲区能在程序性能方面带来明显好处时分配它们。
直接字节缓冲区还可以通过 mapping 将文件区域直接映射到内存中来创建。Java 平台的实现有助于通过 JNI 从本机代码创建直接字节缓冲区。如果以上这些缓冲区中的某个缓冲区实例指的是不可访问的内存区域,则试图访问该区域不会更改该缓冲区的内容,并且将会在访问期间或稍后的某个时间导致抛出不确定的异常。
字节缓冲区是直接缓冲区还是非直接缓冲区可通过调用其 isDirect 方法来确定。提供此方法是为了能够在性能关键型代码中执行显式缓冲区管理。
五、缓冲区使用步骤
在NIO中,数据的读写操作始终是与缓冲区相关联的.读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入缓冲区.缓冲区是定长的,基本上它只是一个列表,它的所有元素都是基本数据类型.ByteBuffer是最常用的缓冲区,它提供了读写其他数据类型的方法,且信道的读写方法只接收ByteBuffer.因此ByteBuffer的用法是有必要牢固掌握的.
1.创建ByteBuffer
1.1 使用allocate()静态方法
ByteBuffer buffer=ByteBuffer.allocate(256);
以上方法将创建一个容量为256字节的ByteBuffer,如果发现创建的缓冲区容量太小,唯一的选择就是重新创建一个大小合适的缓冲区.
1.2 通过包装一个已有的数组来创建
如下,通过包装的方法创建的缓冲区保留了被包装数组内保存的数据.
ByteBuffer buffer=ByteBuffer.wrap(byteArray);
如果要将一个字符串存入ByteBuffer,可以如下操作:
String sendString="你好,服务器. ";
ByteBuffer sendBuffer=ByteBuffer.wrap(sendString.getBytes("UTF-16"));
2.回绕缓冲区
buffer.flip();
这个方法用来将缓冲区准备为数据传出状态,执行以上方法后,输出通道会从数据的开头而不是末尾开始.回绕保持缓冲区中的数据不变,只是准备写入而不是读取.
3.清除缓冲区
buffer.clear();
这个方法实际上也不会改变缓冲区的数据,而只是简单的重置了缓冲区的主要索引值.不必为了每次读写都创建新的缓冲区,那样做会降低性能.相反,要重用现在的缓冲区,在再次读取之前要清除缓冲区.
4.从套接字通道(信道)读取数据
int bytesReaded=socketChannel.read(buffer);
执行以上方法后,通道会从socket读取的数据填充此缓冲区,它返回成功读取并存储在缓冲区的字节数.在默认情况下,这至少会读取一个字节,或者返回-1指示数据结束.
5.向套接字通道(信道)写入数据
socketChannel.write(buffer);
此方法以一个ByteBuffer为参数,试图将该缓冲区中剩余的字节写入信道.
缓冲区(Buffer)其实他有两个子类:一个是HeapByteBuffer和DirectByteBuffer关于这两个类的区别很好理解:
DirectByteBuffer不是分配在堆上的,它不被GC直接管理(但Direct Buffer的JAVA对象是归GC管理的,只要GC回收了它的JAVA对象,操作系统才会释放Direct Buffer所申请的空间),它似乎给人感觉是“内核缓冲区(buffer in kernel)”。HeapByteBuffer则是分配在堆上的,或者我们可以简单理解为Heap Buffer就是byte[]数组的一种封装形式,查看JAVA源代码实现,HeapByteBuffer也的确是这样。 说白了就是HeapByteBuffer是在JVM堆内存中分配会被JVM管理回收,但是DirectByteBuffer是直接由系统内存进行分配,不被JVM管理。通过上面的区别看到:
1、创建和释放DirectByteBuffer的代价比HeapByteBuffer得要高,因为JVM堆中分配和释放内存肯定比系统分配和创建内存高效
2、因为平时的read/write,都会在I/O设备与应用程序空间之间经历一个“内核缓冲区”。 DirectByteBuffer就好比是“内核缓冲区”上的缓存,不直接受GC管理;而Heap Buffer就仅仅是byte[]字节数组的包装形式。因此把一个Direct Buffer写入一个Channel的速度要比把一个HeapByteBuffer写入一个Channel的速度要快。
所以这两个类操作起来各有好处,要视情况而定,一般如果是一个ByteBuffer经常被重用的话,就可以使用DirectByteBuffer对象。如果是需要经常释放和分配的地方用HeapByteBuffer对象。
相关推荐
本文将探讨如何在Java中使用DataBuffer这一概念,以便于与ADO.NET进行数据交换。 首先,理解DataBuffer的概念。在.NET Framework中,DataBuffer是一种可以存储二进制数据的缓冲区,通常用于数据传输和处理。在Java...
Java NIO Buffer 过程详解 Java NIO Buffer 是 Java NIO 中的一种重要组件,负责数据的存储和传输。缓冲区是数组,用于存储不同数据类型的数据。在与 NIO 通道交互时,Java NIO Buffer plays a crucial role. 基本...
在计算机科学领域,Buffer(缓冲区)是一种重要的概念,它在数据处理中起着至关重要的作用。Buffer的应用广泛,特别是在网络编程,尤其是Socket编程中,它扮演着数据传输的桥梁角色。本文将深入探讨Buffer的基本原理...
本话题主要探讨如何使用Java实现一个基于多线程的BUFFER(缓冲区),以支持生产者和消费者之间的互斥操作。这种模式常见于分布式系统、并发编程以及大数据处理等领域。 **一、多线程基础** 1. **线程的创建与启动*...
下面将详细介绍这两类 Buffer 的特点和使用场景。 Heap Buffer Heap Buffer 是存在于 JVM 的堆上的缓冲区, Heap Buffer 对象都包含一个对应基本数据类型的数组属性。Heap Buffer 不能作为缓冲区参数直接进行系统...
基于java的开发源码-DataBuffer在Java中使用ADO.NET.zip 基于java的开发源码-DataBuffer在Java中使用ADO.NET.zip 基于java的开发源码-DataBuffer在Java中使用ADO.NET.zip 基于java的开发源码-DataBuffer在Java中使用...
标题中的"Protocol Buffer java版本"指的是Protocol Buffer支持Java语言的实现。 在Java中,Protocol Buffer提供了SDK,允许开发者定义数据结构(称为.proto文件),然后生成对应的Java类,这些类可以用来序列化和...
JAVA源码DataBuffer在Java中使用ADO.NET
Buffer类通常在java.nio包下,是Java I/O系统的核心组件,它能够显著提升性能,因为减少了实际物理磁盘访问的次数。 1. **缓冲区原理**: 缓冲区的基本思想是先将数据加载到内存中的一个特定区域(即缓冲区),...
本教程将深入探讨如何在Java中使用基于ADO.NET的数据缓冲区——DataBuffer。 首先,理解DataBuffer。在ADO.NET中,DataBuffer是一个用于临时存储数据的内存缓冲区,通常用于处理大数据量或进行复杂的数据操作。它...
- Protocol Buffer:PB的设计目标之一就是跨语言兼容,它支持多种编程语言,包括C++、Java、Python等,方便多语言环境下的数据交换。 - Java序列化:主要针对Java平台,跨语言支持较差,若要在非Java环境中使用,...
如果在描述中提到的“基于java的DataBuffer在Java中使用ADO.NET”,可能是指开发者尝试用DataBuffer来模拟或实现类似ADO.NET的数据缓冲功能。 2. **Java数据库连接(JDBC)** 在Java中,我们通常使用Java Database...
综上所述,"Storage and Buffer ManagerJAVA实现"项目涵盖了Java编程、数据结构、算法、并发控制、锁机制以及数据库理论等多个方面的知识。实现这样的系统需要扎实的编程基础和对数据库原理的理解,同时也为深入学习...
在通信程序中,经常使用环形缓冲区作为数据结构来存放通信中发送和接收的数据。环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问。 1、环形缓冲区的实现原理 环形缓冲区通常有一个读...
在Java编程环境中,`DataBuffer` 是一个核心概念,尤其在处理图像数据时扮演着重要角色。`DataBuffer` 类是Java AWT(Abstract Window Toolkit)和Swing库中的一个关键组件,它负责存储图像像素的数据。在本讨论中,...
【标题】:“DataBuffer在Java中使用ADO.NET”的源码分析 【描述】:这个压缩包包含了一组Java源码,展示了如何在Java环境中利用ADO.NET技术处理数据缓冲区(DataBuffer)。通常,ADO.NET是.NET框架中的一个数据库...
标题中的“基于Java的源码-DataBuffer在Java中使用ADO.NET”暗示了这是一个关于Java编程的项目,其中可能涉及到使用ADO.NET技术在Java环境中处理数据。虽然ADO.NET通常是与微软的.NET框架关联的,但这里提到的是在...
在Java编程中,`DataBuffer` 是一个核心的抽象类,它是用于存储各种类型数据的缓冲区。在Java 2D API中,`DataBuffer` 是图像数据的主要存储结构,通常与`Raster` 和 `BufferedImage` 类一起使用来处理图像。在ADO...
线缓冲区的生成就是其中之一。 以下是一个简单的Java代码示例,展示了如何使用JTS库生成线缓冲区: ```java import org.locationtech.jts.geom.*; import org.locationtech.jts.io.ParseException; import org....