当前位置:首页 > 技术 > 正文内容

Java NIO缓冲区详解:核心概念与基础操作

访客 技术 2026年8月19日 1

缓冲区(Buffer)概述

缓冲区本质上是一块连续的内存区域,用于存储特定类型的数据。从实现角度来看,Java NIO中的Buffer类内部封装了一个基本数据类型的数组,并提供了操作该数组的各种方法。

常见的缓冲区类型包括ByteBuffer、IntBuffer、DoubleBuffer等,它们分别对应byte、int、double等基本数据类型的数组。

缓冲区与通道的交互

在Java NIO架构中,缓冲区主要与通道(Channel)配合使用。数据的传输总是在缓冲区和通道之间进行:要么将缓冲区中的数据写入通道,要么从通道读取数据到缓冲区中。这种设计模式使得I/O操作更加高效和灵活。

缓冲区类层次结构

以ByteBuffer为例,其继承体系如下:

Buffer继承结构

Buffer是顶层抽象类,ByteBuffer继承自Buffer,也是一个抽象类。ByteBuffer的两个主要实现类是:

  • DirectByteBuffer:分配在JVM堆外内存,通过unsafe.allocateMemory实现
  • HeapByteBuffer:分配在JVM堆内内存

缓冲区的核心属性

每个缓冲区都有四个重要属性,它们共同决定了缓冲区的状态和行为:

容量(capacity)

容量表示缓冲区能够容纳的最大元素数量,该值在缓冲区创建时确定且不能更改。例如,创建一个容量为10的字节缓冲区:

ByteBuffer buffer = ByteBuffer.allocate(10);

界限(limit)

界限表示缓冲区中第一个不能被读写元素的索引,也可以理解为缓冲区中当前可操作元素的数量。

位置(position)

位置表示下一个将被读写的元素的索引,该值会随着get()和put()方法的调用而自动更新。

标记(mark)

标记是一个备忘位置。调用mark()方法会将当前position的值保存到mark中,之后调用reset()方法可以将position恢复到之前标记的位置。

这四个属性满足以下关系:0 ≤ mark ≤ position ≤ limit ≤ capacity

缓冲区操作示例

让我们通过一个示例来观察缓冲区属性的变化过程:

1. 创建容量为10的字节缓冲区

ByteBuffer buffer = ByteBuffer.allocate(10);

此时属性状态:mark = -1, position = 0, limit = 10, capacity = 10

初始状态

2. 向缓冲区写入5个字节

buffer.put((byte)'J').put((byte)'a').put((byte)'v').put((byte)'a').put((byte)'!');

此时属性状态:mark = -1, position = 5, limit = 10, capacity = 10

写入数据后

3. 调用flip()方法准备读取

buffer.flip();

此时属性状态:mark = -1, position = 0, limit = 5, capacity = 10

flip操作后

4. 读取两个元素

System.out.println("" + (char) buffer.get() + (char) buffer.get());

此时属性状态:mark = -1, position = 2, limit = 5, capacity = 10

读取数据后

5. 标记当前位置

buffer.mark();

此时属性状态:mark = 2, position = 2, limit = 5, capacity = 10

6. 读取两个元素后恢复到标记位置

System.out.println("" + (char) buffer.get() + (char) buffer.get());
buffer.reset();

执行第一行后:mark = 2, position = 4, limit = 5, capacity = 10

继续读取后

执行第二行后:mark = 2, position = 2, limit = 5, capacity = 10

reset操作后

7. 调用compact()方法压缩缓冲区

buffer.compact();

此时属性状态:mark = 2, position = 3, limit = 10, capacity = 10

compact操作后

注意compact()方法会丢弃已读数据,保留未读数据,并将位置移动到未读数据之后,为新的写入操作做准备。

缓冲区比较机制

缓冲区的相等性判断遵循特定规则。以下是ByteBuffer的equals方法实现:

public boolean equals(Object ob) {
    if (this == ob)
        return true;
    if (!(ob instanceof ByteBuffer))
        return false;
   ByteBuffer that = (ByteBuffer)ob;
    if (this.remaining() != that.remaining())
        return false;
    int p = this.position();
    for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--)
        if (!equals(this.get(i), that.get(j)))
            return false;
    return true;
}

两个缓冲区被视为相等的条件是:

  1. 两个对象类型相同。不同数据类型的缓冲区永远不会相等。
  2. 两个对象剩余元素数量相同。缓冲区容量可以不同,剩余数据的索引位置也可以不同,但从position到limit之间的元素数量必须相同。
  3. 两个缓冲区中剩余数据元素序列必须完全一致。

批量数据操作

ByteBuffer提供了多种批量读写数据的方法:

public ByteBuffer get(byte[] dest, int offset, int length)
public ByteBuffer put(byte[] src, int offset, int length)
public ByteBuffer get(byte[] dest)
public final ByteBuffer put(byte[] src)

后两种方法实际上是前两种方法的简化形式。参数含义如下(以put方法为例):

/*
 * @param  src
 *         要读取的字节数组
 *
 * @param  offset
 *         数组中第一个要读取的字节的偏移量;
 *         必须非负且不大于 array.length
 *
 * @param  length
 *         要从给定数组中读取的字节数;
 *         必须非负且不大于 array.length - offset
 */

批量操作可以显著提高I/O效率,特别是在处理大量数据时。

标签: Java
返回列表

上一篇:Dify 私有化部署实践指南

没有最新的文章了...

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

linux screen 用法详情 (nohup 的替代方案)

一、screen 是什么?能干嘛?screen 是一个终端复用器,可以:在一个 SSH 会话中开多个“虚拟终端”SSH 断线后,程序仍然在后台运行随时重新连接到原来的会话特别适合:nohup 的替代方案跑脚本 / 爬虫 / 训练模型运维、远程开发二、安装 screen# CentOS / Rocky / Almayum install -y screen# Debian / Ubuntuapt i...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。