庖丁解牛:NIO核心概念与机制详解 02 _ 缓冲区的细节实现

文章目录

  • Pre
  • Overview
  • 状态变量
    • 概述
    • Position
    • Limit
    • Capacity
    • 演示: 观察变量
  • 访问方法
    • get() 方法
    • put()方法
    • 类型化的 get() 和 put() 方法
  • 缓冲区的使用:一个内部循环

在这里插入图片描述


Pre

庖丁解牛:NIO核心概念与机制详解 01


接下来我们来看下缓冲区内部细节

Overview

接下来将介绍 NIO 中两个重要的缓冲区组件:状态变量和访问方法 (accessor)

状态变量是"内部统计机制"的关键。每一个读/写操作都会改变缓冲区的状态。通过记录和跟踪这些变化,缓冲区就可能够内部地管理自己的资源。

在从通道读取数据时,数据被放入到缓冲区。在有些情况下,可以将这个缓冲区直接写入另一个通道,但是在一般情况下,您还需要

  • 查看数据。这是使用 访问方法 get() 来完成的。
  • 同样,如果要将原始数据放入缓冲区中,就要使用访问方法 put()。

状态变量

概述

可以用三个值指定缓冲区在任意时刻的状态:

  • position
  • limit
  • capacity

这三个变量一起可以跟踪缓冲区的状态和它所包含的数据。

我们将详细分析每一个变量,还要介绍它们如何适应典型的读/写(输入/输出)进程。在这个例子中,我们假定要将数据从一个输入通道拷贝到一个输出通道


Position

可以回想一下,缓冲区实际上就是美化了的数组。在从通道读取时,将所读取的数据放到底层的数组中。 position 变量跟踪已经写了多少数据。更准确地说,它指定了下一个字节将放到数组的哪一个元素中。

因此,如果从通道中读三个字节到缓冲区中,那么缓冲区的 position 将会设置为3,指向数组中第四个元素。

同样,在写入通道时,是从缓冲区中获取数据。 position 值跟踪从缓冲区中获取了多少数据。更准确地说,它指定下一个字节来自数组的哪一个元素。因此如果从缓冲区写了5个字节到通道中,那么缓冲区的 position 将被设置为5,指向数组的第六个元素。


Limit

limit 变量表明还有多少数据需要取出(在从缓冲区写入通道时),或者还有多少空间可以放入数据(在从通道读入缓冲区时)。

position 总是小于或者等于 limit。


Capacity

缓冲区的 capacity 表明可以储存在缓冲区中的最大数据容量。实际上,它指定了底层数组的大小 ― 或者至少是指定了准许我们使用的底层数组的容量。

limit 决不能大于 capacity。


演示: 观察变量

我们首先观察一个新创建的缓冲区。 我们假设这个缓冲区的 总容量 为8个字节。

在这里插入图片描述

图给你画好了,戳这里


访问方法

到目前为止,我们只是使用缓冲区将数据从一个通道转移到另一个通道。然而,程序经常需要直接处理数据。例如,可能需要将用户数据保存到磁盘。在这种情况下,必须将这些数据直接放入缓冲区,然后用通道将缓冲区写入磁盘。

或者,可能想要从磁盘读取用户数据。在这种情况下,要将数据从通道读到缓冲区中,然后检查缓冲区中的数据。

get() 方法

在这里插入图片描述

ByteBuffer 类中有四个 get() 方法:

1byte get();
2ByteBuffer get( byte dst[] );
3ByteBuffer get( byte dst[], int offset, int length );
4byte get( int index );
  • 第一个方法获取单个字节。
  • 第二和第三个方法将一组字节读到一个数组中。
  • 第四个方法从缓冲区中的特定位置获取字节。

那些返回 ByteBuffer 的方法只是返回调用它们的缓冲区的 this 值。

此外,我们认为前三个 get() 方法是相对的,而最后一个方法是绝对的。 相对 意味着 get() 操作服从 limitposition 值 ― 更明确地说,字节是从当前 position 读取的,而 positionget 之后会增加。

另一方面,一个 绝对 方法会忽略 limitposition 值,也不会影响它们。事实上,它完全绕过了缓冲区的统计方法。

上面列出的方法对应于 ByteBuffer 类。其他类有等价的 get() 方法,这些方法除了不是处理字节外,其它方面是是完全一样的,它们处理的是与该缓冲区类相适应的类型。


put()方法

在这里插入图片描述
ByteBuffer 类中有五个 put() 方法:

1ByteBuffer put( byte b );
2ByteBuffer put( byte src[] );
3ByteBuffer put( byte src[], int offset, int length );
4ByteBuffer put( ByteBuffer src );
5ByteBuffer put( int index, byte b );
  • 第一个方法 写入(put) 单个字节。
  • 第二和第三个方法写入来自一个数组的一组字节。
  • 第四个方法将数据从一个给定的源 ByteBuffer 写入这个 ByteBuffer
  • 第五个方法将字节写入缓冲区中特定的 位置 。那些返回 ByteBuffer 的方法只是返回调用它们的缓冲区的 this 值。

get() 方法一样,我们将把 put() 方法划分为 相对 或者 绝对 的。前四个方法是相对的,而第五个方法是绝对的。

上面显示的方法对应于 ByteBuffer 类。其他类有等价的 put() 方法,这些方法除了不是处理字节之外,其它方面是完全一样的。它们处理的是与该缓冲区类相适应的类型。


类型化的 get() 和 put() 方法

除了前些小节中描述的 get()put() 方法, ByteBuffer 还有用于读写不同类型的值的其他方法。

在这里插入图片描述

如下所示:

getByte()
getChar()
getShort()
getInt()
getLong()
getFloat()
getDouble()
putByte()
putChar()
putShort()
putInt()
putLong()
putFloat()
putDouble()

事实上,这其中的每个方法都有两种类型 ― 一种是相对的,另一种是绝对的。它们对于读取格式化的二进制数据(如图像文件的头部)很有用。

举个栗子

public class TypesInByteBuffer
{static public void main( String args[] ) throws Exception {ByteBuffer buffer = ByteBuffer.allocate( 64 );buffer.putInt( 30 );buffer.putLong( 7000000000000L );buffer.putDouble( Math.PI );buffer.flip();System.out.println( buffer.getInt() );System.out.println( buffer.getLong() );System.out.println( buffer.getDouble() );}
}

缓冲区的使用:一个内部循环

下面的内部循环概括了使用缓冲区将数据从输入通道拷贝到输出通道的过程

while (true) {buffer.clear();int r = fcin.read( buffer );if (r==-1) {break;}buffer.flip();fcout.write( buffer );
}
  • read()write() 调用得到了极大的简化,因为许多工作细节都由缓冲区完成了。
  • clear()flip() 方法用于让缓冲区在读和写之间切换。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/151729.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何学习算法

在不知其所以然的情况下,算法只是一堆离散的机械步骤,缺少背后的思想的支撑, 这些步骤之间就没有一个本质层面上的关联(先知亚里士多德早就指出:学习即联接)。 所以就跟背历史书也没多大区别。然而&#xf…

IPO解读丨高处不胜寒,澜沧古茶低头取暖?

自A股注册制改革不断深化并全面落地后,不少意欲登陆资本市场的企业转战港股。这个过程中,诞生了很多以“港股”为前缀的“第一股”——“白酒第一股”珍酒李渡、“水果零售第一股”百果园、“智能驾驶第一股”知行汽车、“运动科技第一股”Keep…… 由A…

实现CAS自旋锁

CAS 在高并发场景,可以使用加锁、CAS来保证原子性,但是加锁是很重量级的操作,CAS类似于乐观锁CAS ( Compare and swap )比较并交换,是实现并发算法时常用到的技术,包含三个操作数:内…

力扣刷题-二叉树-完全二叉树的节点个数

222.完全二叉树的节点个数 给出一个完全二叉树,求出该树的节点个数。 示例 1: 输入:root [1,2,3,4,5,6] 输出:6 示例 2: 输入:root [] 输出:0 示例 3: 输入:root [1]…

springMvc中的拦截器【巩固】

先实现下想要的拦截器功能 package com.hmdp.utils;import com.hmdp.entity.User; import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Ht…

Pandas get_dummies用法

get_dummies 是 pandas 实现one hot encode的方式 ​  one-hot的基本思想:将离散型特征的每一种特征取值都看成一种状态,若指定离散特征中有N个 不相同的取值,那么我们就可以将该特征抽象成N种不同的状态,one-hot编码保证了每一…

10 Redis的持久化

Redis支持RDB和AOF两种持久化机制 1、RDB(Redis DataBase) 是对命令的全量快照随着key的数量增大,那么写入磁盘的开销也会越来越大 2、RDB文件的生成是否会阻塞主线程 save: 使用save的方式会阻塞主线程,影响redis的性能 bgsave: 一般情况下不会阻塞…

05-networkX-结构洞计算

教程仓库地址:github networkx_tutorial import networkx as nx import matplotlib.pyplot as pltimport pandas as pd import networkx as nxdf pd.read_csv(./df.csv,index_col0) df.head()AB0H04N5H04N71G06F3G02F12G06F3H03K173G02F1H03K174NaNNaN # 检查 A 和…

C语言模拟实现Liunx操作系统与用户之间的桥梁shell(代码详解)

什么是shell? Shell(壳)是指命令行界面(CLI)或脚本语言,它为用户提供了与操作系统交互的方式。它是一个程序,从用户那里接收命令,并通过与操作系统内核交互来执行这些命令。Shell充当…

CDN加速在社会发展中的挑战与机遇

随着互联网的迅猛发展,CDN(内容分发网络)加速技术在网络领域的应用逐渐成为推动社会进步的关键因素之一。CDN加速通过在全球范围内分布的服务器群,将内容快速分发到用户,提升了网络性能和用户体验。然而,CD…

CTFHub Git泄露

Log 前言 根据题目描述,这个题目需要使用到工具 GitHack 来完成,而 CTFHub 上提供的工具需要在 python2 环境中执行,注意 python3 环境无法使用。 GitHack准备(kali Linux) 打开虚拟机 sudo su 以管理员的身份运行…

开源更安全? yum源配置/rpm 什么是SSH?

文章目录 1.开放源码有利于系统安全2.yum源配置,这一篇就够了!(包括本地,网络,本地共享yum源)3.rpm包是什么4.SSH是什么意思?有什么功能? 1.开放源码有利于系统安全 开放源码有利于系统安全 2.yum源配置…

Java 11及更高版本的Oracle JDK版本

2021 年 9 月 14 日,Oracle 发布了可以长期支持的 JDK17 版本,那么从 JDK11 到 JDK17,到底带来了哪些特性呢?亚毫秒级的 ZGC 效果到底怎么样呢?值得我们升级吗?而且升级过程会遇到哪些问题呢?带…

【Spring boot】RedisTemplate中String、Hash、List设置过期时间

文章目录 前言Redis中String设置时间的方法Redis中Hash和List设置时间的方法Redis中Hash的put、putAll、putIfAbsent区别 前言 时间类型:TimeUnit import java.util.concurrent.TimeUnit;TimeUnit.SECONDS:秒 TimeUnit.MINUTES:分 TimeUnit.HOURS&…

Javaweb之Ajax的详细解析

1.1 Ajax介绍 1.1.1 Ajax概述 我们前端页面中的数据,如下图所示的表格中的学生信息,应该来自于后台,那么我们的后台和前端是互不影响的2个程序,那么我们前端应该如何从后台获取数据呢?因为是2个程序,所以…

cobol基本语法

字符集 包括78个字符 A-Z a-z 0-9 (空格 - * / $ ,(逗号) ;(分号) .(小数点或英文句号) ""(双引号) ((左括号) )(右括号&…

“移动机器人课程群实践创新的困境与突围”素材

以下是一篇应用型本科教研论文“移动机器人课程群实践创新的困境与突围”的大纲。您可以根据这个大纲展开您的论文写作: 一、引言 移动机器人技术的发展和应用价值移动机器人课程群在应用型本科教育中的重要性论文目的和研究问题:解析移动机器人课程群实…

利用OpenCV做个熊猫表情包 二

之前写了一篇 利用OpenCV做个熊猫表情包吧_Leen的博客-CSDN博客 回想起来觉得有点太弱了,意犹未尽,每次使用需要自己去手动截取人脸,清除黑边什么的才能使用demo去合成表情,无奈之前由于安装的vs,opencv版本都比较低…

扩散模型实战(十):Stable Diffusion文本条件生成图像大模型

推荐阅读列表: 扩散模型实战(一):基本原理介绍 扩散模型实战(二):扩散模型的发展 扩散模型实战(三):扩散模型的应用 扩散模型实战(四&#xff…

【推荐】智元兔AI:一款集写作、问答、绘画于一体的全能工具!

在当今技术飞速发展的时代,越来越多的领域开始应用人工智能(Artificial Intelligence,简称AI)。其中,AI写作工具备受瞩目,备受推崇。在众多的选择中,智元兔AI是一款在笔者使用过程中非常有帮助的…