- Channel 负责传输, Buffer 负责存储
缓冲区(Buffer)
- 特定基本数据类型的容器。由 java.nio 包定义的,所有缓冲区都是 Buffer 抽象类的子类
- 负责数据 的存取 ,缓冲区就是数组, 用于存储不同的数据
- 据类型的不同 (Boolean 除外) 提供相应类型的缓冲区: Byte Char Short Int Long Float Double
- 获取缓冲区 :static XxxBuffer allocate(int capacity) : 创建一个容量为 capacity 的 XxxBuffer 对象
缓冲区的相关属性
- 容量 (capacity) :表示 Buffer 最大数据容量,缓冲区容量不能为负,并且创建后不能更改。
- 限制 (limit):界限 ,表示缓冲区中可以操作数据的大小 (limit 后面的数据不能进行读写)。
- 位置 (position):位置 表示缓冲区中正在操作 数据的位置
- 标记 (mark)与重置 (reset):标记是一个索引,通过 Buffer 中的 mark() 方法指定 Buffer 中一个特定的 position,之后可以通过调用 reset() 方法恢复到这个 position.
- 标记、位置、限制、容量遵守以下不变式: 0 <= mark <= position <= limit <= capacity

缓冲区存取数据的三个核心方法
- put :存入缓冲区
- get : 获取缓冲区数据
- flip :切换 到读取数据的模式
-
相关方法
- get() :读取单个字节
- get(byte[] dst):批量读取多个字节到 dst 中
- get(int index):读取指定索引位置的字节(不会移动 position)
- put(byte b):将给定单个字节写入缓冲区的当前位置
- put(byte[] src):将 src 中的字节写入缓冲区的当前位置
- put(int index, byte b):将指定字节写入缓冲区的索引位置(不会移动 position)
Buffer 的常用方法
| 方 法 | 描 述 |
|---|---|
| Buffer clear() | 清空缓冲区并返回对缓冲区的引用,缓冲区数据还在 处于被遗忘状态 |
| Buffer flip() | 将缓冲区的界限设置为当前位置,并将当前位置重置为 0 |
| int capacity() | 返回 Buffer 的 capacity 大小 |
| boolean hasRemaining() | 判断缓冲区中是否还有元素 |
| int limit() | 返回 Buffer 的界限(limit) 的位置 |
| Buffer limit(int n) | 将设置缓冲区界限为 n, 并返回一个具有新 limit 的缓冲区对象 |
| Buffer mark() | 对缓冲区设置标记 |
| int position() | 返回缓冲区的当前位置 position |
| Buffer position(int n) | 将设置缓冲区的当前位置为 n , 并返回修改后的 Buffer 对象 |
| int remaining() | 返回 position 和 limit 之间的元素个数 |
| Buffer reset() | 将位置 position 转到以前设置的 mark 所在的位置 |
| Buffer rewind() | 将位置设为为 0, 取消设置的 mark,可重复读数据 |
直接与非直接缓冲区
- 字节缓冲区要么是直接的,要么是非直接的。如果为直接字节缓冲区,则 Java 虚拟机会尽最大努力直接在此缓冲区上执行本机 I/O 操作。也就是说,在每次调用基础操作系统的一个本机 I/O 操作之前(或之后),虚拟机都会尽量避免将缓冲区的内容复制到中间缓冲区中(或从中间缓冲区中复制内容)。
- 直接字节缓冲区可以通过调用此类的 allocateDirect() 工厂方法来创建。此方法返回的缓冲区进行分配和取消分配所需成本通常 高于 非直接缓冲区。直接缓冲区的内容可以驻留在常规的垃圾回收堆之外,因此,它们对应用程序的内存需求量造成的影响可能并不明显。所以, 建议 将直接缓冲区 主要 分配给那些易受基础系统的本机 I/O 操作影响的大型、持久的缓冲区。一般情况下,最好仅在直接缓冲区能在程序性能方面带来明显好处时分配它们。
- 直接字节缓冲区还可以通过 FileChannel 的 map() 方法 将文件区域直接映射到内存中来创建。该方法返回MappedByteBuffer 。Java 平台的实现有助于通过 JNI 从本机代码创建直接字节缓冲区。如果以上这些缓冲区中的某个缓冲区实例指的是不可访问的内存区域,则试图访问该区域不会更改该缓冲区的内容,并且将会在访问期间或稍后的某个时间导致抛出不确定的异常。
- 字节缓冲区是直接缓冲区还是非直接缓冲区可通过调用其 isDirect() 方法来确定。提供此方法是为了能够在性能关键型代码中执行显式缓冲区管理。
- 直接缓冲区缺点 : 消耗大 、 不能受 jvm 管理 、得通过System.gc 垃圾回收机制进行释放连接
-
非直接缓冲区

-
直接缓冲区

直接缓冲区获取方式:
- 2 、1.7 中NIO.2 针对各种通道提供了静态方法 FileChannel.open
- 3 、1.7 中NIO.2 中的Files工具类的newByteChannel
本文深入探讨Java NIO中的缓冲区概念,包括Buffer的基本作用、类型、获取方式及核心方法如put、get、flip等的使用。同时,对比直接缓冲区与非直接缓冲区的特性,帮助理解数据传输与存储的机制。
2007

被折叠的 条评论
为什么被折叠?



