Java NIO 入门(四)Buffer内部原理

Java NIO 入门(四)Buffer内部原理
guibin.beijing@gmail.com

[size=medium]概述[/size]
在这节中,我们将关注NIO的Buffer中两个重要的组件:状态变量和访问方法。
状态变量对于前面提到的“内部计数系统”而言相当重要,每次进行完读写之后,Buffer的状态都随之改变。通过记录和跟踪这些改变,Buffer才可以把Buffer内部的资源管理好。

当你从Channel中读数据时,数据首先放到了Buffer中。在某些情况下,你可以直接把这个Buffer写入另一个Channel中,但是通常情况下,你可能想看看数据内容,这个想法可以通过方法get()实现。相似的,当你想要把原始数据放进Buffer中,你可以使用put()方法。

在这节中,我们将学习NIO中的状态变量和访问方法。每个组件都会涉及到,并且有机会查看具体的使用。然而NIO的内部计数系统起初看起来可能有些复杂,你很快会看到内部计数系统实际上为你做了哪些事情。

[size=medium]状态变量[/size]
总共有三个值可以被用来表示在给定的任何时刻Buffer的状态,他们分别是:
[list]
[*]position
[*]limit
[*]capacity
[/list]
这三个变量跟踪了Buffer的状态和Buffer所包含的数据。
接下来我们将逐一检查每个细节,并且也看看为什么这样的设计适合典型的读/写(输入/输出)处理。比如仅仅这个例子,我们假设从一个Channel拷贝数据到另一个Channel。

[size=medium]Position[/size]
回忆一下,Buffer实际上也就是个array。当你从Channel中读数据时,你把从Channel中读出来的数据放进底层array,[color=red][size=medium]position变量用来跟踪截止目前为止已经写了多少数据。更精确的讲,它指示如果下次写Buffer时数据应该进入array的哪个位置[/size][/color]。因此如果已经从Channel中读出了3个字节,Buffer的position会被置为3,指向array中第四个位置。
相似的,如果正在向Channel中写入数据,你需要从Buffer中获取要写的数据,此时position持续的跟踪你已经从Buffer中读取了多少数据。更精确的说,position指示了下一次从Buffer中读取数据时将读入array的哪个元素。因此如果你已经向Channel中写了5个byte,Buffer的position被置为5,指向array中第六个元素。

[size=medium]Limit[/size]
[color=red][size=medium]在从Buffer中向Channel中写数据时,limit变量指示了还剩多少数据可以读取,在从Channel中读取数据到Buffer中时,limit变量指示了还剩多少空间可供存放数据。[/size][/color]
position正常情况下小于或者等于limit。

[size=medium]Capacity[/size]
Buffer的[color=red][size=medium]Capacity指示Buffer最多能够存储的数据。实际上,它指示了底层array的容量,或者至少是底层array允许使用的空间数量。[/size][/color]
Limit永远不会大于capacity。

[size=medium]以实例来观察这三个变量[/size]
我们从一个新建的Buffer开始。由于是例子的缘故,我们假设Buffer有一个8字节大小的Capacity。此时Buffer的状态如下所示:
[img]http://dl.iteye.com/upload/attachment/553345/ad8f6af7-3b54-321c-a24f-48acd98f4ecf.png[/img]

回忆之前所讲的,limit不会大于capacity,在这个例子中,limit和capacity都会被设为8。我们通过在array尾部用箭头指示的方式表示。
[img]http://dl.iteye.com/upload/attachment/553351/b7af0315-5b3a-3a43-8008-a52c60258d1e.png[/img]

此时position设置为0。如果我们从Channel读了一些数据进入Buffer,下一个字节将会被存入位置为0的地方。如果我们从Buffer中写数据进入Channel,Buffer中下一个被读的字节将从位置0取得。position的设置如下图所示:

[img]http://dl.iteye.com/upload/attachment/553353/ca9d0263-c6e1-358b-a63b-e6df55834420.png[/img]

因为capacity一旦设置好就不会改变了,之后的讨论我们将暂时忽略capacity。

[size=medium]第一次读操作[/size]
现在我们准备好了在我们新建的Buffer上开始读/写操作了。我们开始从Channel中读一些数据进入Buffer,第一次读3个字节。读之前position为0,读完后position从0增长到3,如下所示:
[img]http://dl.iteye.com/upload/attachment/553356/46108444-93d9-3696-af39-e5b9f1f993e9.png[/img]

[size=medium]第二次读操作[/size]
第二次读操作,我们将再读2个字节从Channel到Buffer中,这两个字节存储的位置从之前的position即3开始,读完后position增加了2变为5。如下图:

[img]http://dl.iteye.com/upload/attachment/553359/f488db0c-fae5-38c4-bf56-fc298138b017.png[/img]

[size=medium]Flip操作[/size]
到目前位置,我们结束了从Channel中读的操作,现在开始将数据写入输出Channel中。在做写操作之前,我们必须调用一次flip()方法,这个方法做了两件重要的事情:
1. 将limit设置到当前的position处。
2. 设置position为0。
上幅图展示了在执行flip之前的Buffer,下面这幅图展示了执行了flip() 之后的Buffer:

[img]http://dl.iteye.com/upload/attachment/553371/df701f24-5f5d-3400-8c0d-87ca2d716dcf.png[/img]

现在我们已经准备好了把数据从Buffer中写到Channel中。Position已经设置为0,意思是说我们将获得的下一个字节为位置为0的字节,limit已经设置到了之前的position处,意思是此时Buffer中包含有之前读入Buffer中的所有字节。

[size=medium]第一次写操作[/size]
在我们第一次的写操作中,我们从Buffer中取出4个字节,然后写入output channel中。这个操作使得position从0增加到4,而limit没有变化,如下所示:

[img]http://dl.iteye.com/upload/attachment/553374/90c263fd-8386-3e65-8da6-fafe91441b41.png[/img]

[size=medium]第二次写操作[/size]
目前为止,只剩一个字节可写了。当我们调用flip()时,limit被设置成5,并且position不能超越limit。因此最后的写操作从Buffer取出一个字节并写入output Channel中。这次写操作会将position增加到5,而limit不变。如下所示:

[img]http://dl.iteye.com/upload/attachment/553425/040df516-bc16-3655-b0e4-83d74327f2a2.png[/img]

[size=medium]Clear操作[/size]
在我们的最后一步是调用Clear方法。这个方法会重置Buffer以准备接收新数据。Clear做了2件重要的事情:
1. 设置limit为0以匹配capacity。
2. 设置position为0。
下面的图展示了当调用完flip()之后的Buffer的状态:

[img]http://dl.iteye.com/upload/attachment/553447/9c7f18ba-afb2-3cb4-b7d7-69d190aaf5e6.png[/img]

[size=medium]一个能工作的Buffer[/size]
下面的代码总结了使用Buffer从一个Channel拷贝数据到另一个Channel

while(trie) {
buffer.clear();
int r = fcin.read( buffer );

if (r==-1) {
break;
}

buffer.flip();
fcout.write( buffer );
}

read()和write()方法极大的简化了程序,由于Buffer处理了所有的细节。clear()和flip()方法用来切换Buffer的读和写。

本文参考自[url]http://www.cs.brown.edu/courses/cs161/papers/j-nio-ltr.pdf[/url]
《Java源码解析》NIO中的heap Buffer和direct Buffer区别 heap buffer 和 direct buffer区别在Java的NIO中,我们一般采用ByteBuffer缓冲区来传输数据,一般情况下我们创建Buffer对象是通过ByteBuffer的两个静态方法:ByteBuffer.allocate(int capacity); ByteBuffer.wrap(byte[] array);查看JDK的NIO的源代码关于这两个部分:/**allocate( 阅读详情

相关推荐

Java NIO 详解---Buffer与Channel

一.NIO 和BIO的比较 NIO是jdk1.4开始提供的一种新的IO方式。原来的 I/O 库(在 java.io.*中) 与 NIO 最重要的区别是数据打包和传输的方式。原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。面向流 的 I/O 系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易。链接几个过滤器

荒野孤鹰 2312

NIO Buffer 实现原理

目前很多高性能的Java RPC框架都是基于Netty实现的,而Netty的设计原理又离不开Java NIO。本篇笔记是对NIO核心三件套:缓冲区(Buffer)、选择器 (Selector)和通道(Channel),其中之一的实现原理的学习总结。

兴趣使然的草帽路飞 1万+

打通Creo与Matlab的桥梁:Simscape Multibody Link插件安装与配置全攻略

本文详细介绍了Simscape Multibody Link插件的安装与配置全流程,旨在帮助机械工程师和开发者打通Creo与Matlab/Simulink之间的桥梁,实现CAD模型到多体动力学仿真的高效转换。文章重点解析了版本兼容性、管理员权限、注册文件配置等关键步骤与常见故障排查方法,助力用户快速建立设计与仿真一体化工作流。

rrr55的博客 634

NIO 之 Buffer 图解

可参考之前的文章:NIO 之 ByteBuffer实现原理 下面是对之前文章的一个补充 Buffer 类 结构 对于每个非布尔原始数据类型都有一个缓冲区类。尽管缓冲区作用于它们存储的原始数据类型,但缓冲区十分倾向于处理字节。 概述 缓冲区 Buffer 内部就是用数组实现的。 Buffer 包含了下面4个属性: 容量( Capacity) 缓冲区能够容纳的数据元素的最大...

jijianshuai的专栏 1849

ROS下UR+Realsense相机进行手眼标定

手眼标定主要是用来确定相机坐标系和机械臂坐标系之间的转换关系,从而实现后续的抓取等任务。

weixin_42157689的博客 7569

InfiniBand(IB)实战指南:从硬件配置到性能优化

本文是一份详尽的InfiniBand实战指南,涵盖从硬件选型、部署到驱动配置、性能优化的全流程。重点解析了InfiniBand作为AI训练与高性能计算(HPC)核心网络的优势,特别是其支持的RDMA技术如何实现微秒级低延迟。文章提供了硬件匹配、NCCL压测、内核参数调优及在PyTorch分布式训练中启用IB的实操步骤,旨在帮助工程师构建和优化高性能计算集群。

mqtt6iot的博客 578

Java NIO三件套之Buffer实现原理解析

各位读者,由于本篇幅度过长,为了避免影响阅读体验,下面我就大概概括了整理了久(就是缓冲区的数据会被重复利用)的缓冲区,一般情况下,最好仅在直接缓冲区能在程序性能带来非常明显的好处时才分配它们。直接缓冲区还可以通过FileCHannel的map()方法将文件区域映射到内存中来创建,该方法返回MappedByteBuffer。

2401_85112148的博客 942

OpenWrt kmod内核不兼容?手把手教你用脚本强制安装驱动模块(附国内镜像源)

本文详细解决了OpenWrt kmod内核不兼容问题,提供智能脚本强制安装驱动模块的方法,并附有国内镜像源加速配置。通过自动化脚本修改内核MD5校验值,确保kmod包正常安装,同时推荐多个国内镜像源以提升下载速度。

weixin_42549451的博客 540

NIO组件之Buffer详解

Buffer类的capacity属性,表示内部容量的大小。一旦写入的对象数量超过了capacity容量,缓冲区就满了,不能再写入了。Buffer类的capacity属性一旦初始化,就不能再改变。原因是什么呢?Buffer类的对象在初始化时,会按照capacity分配内部数组的内存,在数组内存分配好之后,它的大小当然就不能改变了。Buffer类是一个抽象类,Java不能直接用来新建对象。属性说明capacity容量,即可以容纳的最大数据量;在缓冲区创建时设置并且不能改变limit。...

ntzzzsj的博客 1506

DDR4内存PCB设计实战:8层板Fly-by拓扑信号完整性优化

本文深入探讨了DDR4内存条在8层PCB板上采用Fly-by拓扑时的信号完整性优化实战。文章详细解析了层叠规划、阻抗控制、电源分割、等长布线及串扰抑制等关键设计要点,并强调了仿真验证的重要性,为硬件工程师提供了从理论到实践的完整设计指南与自查清单。

weixin_29296241的博客 340

面向 OData V4 的 Fiori elements 为何强制使用 draft、它到底是什么、以及是否能关闭

本文深入解析了SAP Fiori elements中draft handling的核心机制与必要性。关键点包括:1)draft机制通过中间版本实现复杂编辑的安全恢复与并发控制;2)Fiori elements for OData V4强制要求draft-enabled服务支持事务编辑;3)非draft服务仅适用于只读场景;4)替代方案需承担完全自定义开发的成本。文章基于SAP官方文档,系统阐述了draft在事务型应用中的基础性作用,为架构决策提供了明确指导。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 267

mysql(二) Buffer Pool(缓冲池)的内部结构

上一篇mysql(一) 中以一个update语句为例简单的介绍了innodb的大体结构,然而还是存在很多细节问题的,就如上一篇文末提及的几个问题。该篇主要对于InnoDB进行比较详细的分析 一、Buffer Pool (缓冲池) 1、 啊 ...

qq_35599414的博客 1783

RK3588部署实战:利用RGA硬件加速单元优化YOLOv5的图像预处理与推理性能

摘要:本文探讨了在Rockchip芯片上使用RGA(Rockchip图形加速器)实现YOLOv5图像预处理的过程。通过对比RGA和OpenCV两种方式处理图像的速度,发现RGA加速效果不明显且不稳定(13-17fps),分析原因可能是图片尺寸过小和内存操作消耗时间。文章详细介绍了RGA版本的resize和letterbox实现代码,包括图像缩放、边缘填充等功能,并提供了预处理流程和性能监控方法。结果表明在当前场景下RGA尚未达到预期加速效果,可能与官方代码下架和实现细节有关。

know_F0727的博客 293

Java 入门指南:Java NIO —— Buffer(缓冲区)

在 NIO(New Input/Output)模型中,Buffer 是一个重要的概念,与数据打交道,用于在内存中存储数据。通过 Channel 将数据传输到 Buffer 缓冲区中,并在缓冲区内进行数据的读写操作。 Buffer 本质上是一个数组,可以存储多个相同类型的基本数据类型,如 byte、short、int、long、float、double 等。Buffer 封装了内部的数组,并提供了一些操作该数组的方法。

热带鱼的技术博客 2258

YOLOv11 改进 - 注意力机制 | LS-YOLO MSFE 多尺度特征提取模块:并行分支结构增强多尺度感知,优化遥感与小目标检测

本文介绍了一种用于滑坡检测的模型LS-YOLO及其在YOLOv11中的结合应用。LS-YOLO首先构建多尺度滑坡数据集MSLD,为模型训练提供丰富数据。设计了基于高效通道注意力、平均池化和空间可分离卷积的多尺度特征提取模块MSFE,充分提取滑坡特征信息。在解耦头中采用膨胀卷积增加模型感受野。我们将MSFE模块集成进YOLOv11,替换部分原有模块。实验表明,改进后的YOLOv11在数据集中表现出色 。

魔改工程师的博客 870

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

JAVA NIO组件之Buffer详解

Java NIO(New I/O)中,Buffer是一个重要的组件,它作为数据的容器,主要用于数据的读写操作。Buffer本质上是一个内存块,可以写入数据,也可以从中读取数据。

码到三十五 1224

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

【源码解析】Java NIO 包中的 Buffer

Buffer 是 JDK 1.4 引入的 NIO 包下面的一个核心类,主要是为了提供一种更高效、更灵活的方式来进行 I/O 操作。对于传统的 IO ,往往会涉及到多次内存的复制,比如从内核态复制到用户态,再赋值到应用程序缓冲区,Buffer 就提供了一种直接映射内存区域的可能,减少这些数据的复制,提高查询的效率。除此外,Buffer 在 NIO 中用来存储数据的容器,Channel 通过 Buffer 进行读写操作,从而实现高效的 NIO,也就是非阻塞 IO。

Jwasx的博客 1603

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Java Nio 的Buffer和优缺点

在数据传输的时候,我们会用到缓冲区。Java NIO中的Buffer用于和NIO通道进行交互。

WSYW126的博客 3601

Java NIO之Buffer

NIO Buffer 是NIO的核心之一。 在与 NIO Channel 进行交互时, 需要使用 NIO Buffer, 将数据从 Buffer读取到 Channel 或者从 Channel 中写入Buffer 中

学习、学习、再学习 609

三、Java NIO Buffer

Java NIO Buffer

梦想成真 763

Java NIO(Buffer)

Java NIO(Buffer)3.1 Buffer简介3.2 Buffer的基本使用3.2.1 使用Buffer读写数据,一般遵循以下四个步骤3.2.2 使用buffer的例子3.3 Buffer的capacity、position和limit 3.1 Buffer简介 Java NIO中的Buffer用于和NIO通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用于方便

二进制杯莫停的博客 1303

图解Java NIO Buffer

Buffer四个基本属性 1、capacity:能够容纳的最大元素数目,创建时设定并不能更改 2、limit: buffer中有效位置数目 3、position: 下一个读或者写的位置 4、mark: 用于记忆的标志位,配合reset()使用,初始值未设定,调用mark后将当前position设为值 标记、位置、限制和容量值有以下关系: 0 <= 标记 <= 位置 <= 限制 <= 容量

I am not a quitter. 1436

Java - NIO之Buffer(上)

一、关于  Java NIO中的Buffer用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的。 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。

袭冷 1367

Java NIO-Buffer

1 概述 Java NIO中的Buffer用于和NIO通道进行交互。数据是从通道进入缓冲区,从缓冲区写入通道中的。缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成了NIO Buffer对象。在NIO中所有的数据都是用缓冲区处理的。 2 Buffer 使用Buffer一般步骤: 第一步:写入数据到Buffer 第二步:调用flip() 第三步:从Buffer中读取数据 第四步:调用clear()或者compact方法 注意:读取数据时,需要调用flip()方法将

爪哇人的博客 1159

Java随笔记 - Java NIO的初步认识,NIO的三个核心概念,Channel和Buffer的简单使用

Java随笔记 - Java NIO的初步认识,NIO的三个核心概念,Channel和Buffer的简单使用 先从一段简单的代码看起: IntBuffer intBuffer = IntBuffer.allocate(10); for (int i = 0; i < intBuffer.capacity(); i++) { int randomNumber = new SecureRandom().nextInt(20); intBuffer.put(randomNumber);

JiangNanMax的博客 4617

Java NIO(三)NIO之Buffer

系列文章目录 第一篇 Java NIO(一)I/O简介 第一篇 Java NIO(二)BIO 第一篇 Java NIO(三)NIO之Buffer 第一篇 Java NIO(四)NIO之Channel 第一篇 Java NIO(五)NIO之Selector 第一篇 Java NIO(六)Netty) Java NIO(三)NIO之Buffer 目录系列文章目录Java NIO(三)NIO之Buffer前言一、示例代码二、Buffer1. 介绍2. Buffer分类3. Buffer的基本原理4. Buffe

Devinskx的博客 321
上一篇: Java NIO 入门(三)从理论到实践:使用NIO读写
下一篇: ConcurrentHashMap是如何提高并发时的吞吐性能(一)
Guibin
博客等级 码龄23年 45粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值