深入浅出java nio

news/2024/5/17 10:36:19/文章来源:https://blog.csdn.net/qq_37151886/article/details/128189546

Buffer 缓冲

为什么需要缓冲?

思考:没有buffer之前的读写。

子类

在这里插入图片描述
常见类型的缓冲

ByteBuffer

在这里插入图片描述

public abstract class ByteBufferextends Bufferimplements Comparable<ByteBuffer>
{}

ByteBuffer是抽象类无法直接实例化,可以通过allocate等方法返回实例。

allocate

    public static ByteBuffer allocate(int capacity) {if (capacity < 0)throw new IllegalArgumentException();return new HeapByteBuffer(capacity, capacity);}

allocateDirect

    public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);}

ByteBuffer 分为HeapByteBuffer和DirectByteBuffer两种,翻译成人话就是堆字节缓冲和直接字节缓冲,第二种不受 JVM 控制。

        ByteBuffer hbb = ByteBuffer.allocate(1024);ByteBuffer dbb = ByteBuffer.allocateDirect(1024);

在后面的介绍中,hbb代指 JVM 缓冲区,dbb代指直接缓冲区。

HeapByteBuffer

DirectByteBuffer

常见方法

allocate

下面对 allocate 的调用链路参数进行分析。

    public static ByteBuffer allocate(int capacity) {if (capacity < 0)throw new IllegalArgumentException();//capacity >= 0return new HeapByteBuffer(capacity, capacity);}

cap = lim = capacity,由 HeapByteBuffer 构造函数调用 super

    HeapByteBuffer(int cap, int lim) {           super(-1, 0, lim, cap, new byte[cap], 0);}

mark = -1
pos = 0
lim = cap
cap = cap
hb = new byte[cap]
offset = 0

    ByteBuffer(int mark, int pos, int lim, int cap,  byte[] hb, int offset){super(mark, pos, lim, cap); //-1,0,cap,capthis.hb = hb; //new byte[cap]this.offset = offset; //0}

hb字节数组和offset 偏移量为 ByteBuffer 字段。

mark = -1
pos = 0
lim = cap
cap = cap

    Buffer(int mark, int pos, int lim, int cap) { //判断多余 cap > 0     if (cap < 0)throw new IllegalArgumentException("Negative capacity: " + cap);  this.capacity = cap; // 1limit(lim); //2position(pos); //3 //汇总分析的参数 mark = -1,pos = 0if (mark >= 0) {if (mark > pos)throw new IllegalArgumentException("mark > position: ("+ mark + " > " + pos + ")");this.mark = mark;}}

核心代码表示为1,2,3的部分。

    public final Buffer limit(int newLimit) {  // newLimit = lim = capif ((newLimit > capacity) || (newLimit < 0))throw new IllegalArgumentException();limit = newLimit; //limit = newLimit = lim = capif (position > limit) position = limit; // position = 0 limit = capif (mark > limit) mark = -1; // mark = -1return this;}
    public final Buffer position(int newPosition) { // newPosition = pos = pos = 0if ((newPosition > limit) || (newPosition < 0))throw new IllegalArgumentException();position = newPosition; // position =  newPosition = pos = pos = 0if (mark > position) mark = -1;return this;}

所以经过这一串构造函数后,buffer中的值分别为

java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]

pos = 位置,lim = 限制,cap = 容量,最大值。

allocateDirect

    public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);}
    DirectByteBuffer(int cap) {    //cap =  capacity//调用链路super(-1, 0, cap, cap);//boolean pa = VM.isDirectMemoryPageAligned();int ps = Bits.pageSize();long size = Math.max(1L, (long)cap + (pa ? ps : 0));Bits.reserveMemory(size, cap);long base = 0;try {//unsafe 分配内存空间base = unsafe.allocateMemory(size);} catch (OutOfMemoryError x) {Bits.unreserveMemory(size, cap);throw x;}unsafe.setMemory(base, size, (byte) 0);if (pa && (base % ps != 0)) {// Round up to page boundaryaddress = base + ps - (base & (ps - 1));} else {address = base;}cleaner = Cleaner.create(this, new Deallocator(base, size, cap));att = null;}
    MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-privatesuper(mark, pos, lim, cap);this.fd = null;}
    ByteBuffer(int mark, int pos, int lim, int cap) { // package-privatethis(mark, pos, lim, cap, null, 0);}
    ByteBuffer(int mark, int pos, int lim, int cap,   // package-privatebyte[] hb, int offset){super(mark, pos, lim, cap);this.hb = hb;this.offset = offset;}
    Buffer(int mark, int pos, int lim, int cap) {       // package-privateif (cap < 0)throw new IllegalArgumentException("Negative capacity: " + cap);this.capacity = cap;limit(lim);position(pos);if (mark >= 0) {if (mark > pos)throw new IllegalArgumentException("mark > position: ("+ mark + " > " + pos + ")");this.mark = mark;}}

调用过程不再赘述,跟 allocate 链路差不多,区别是使用 unsafe 进行内存分配和其他的操作。

flip 翻转

    public final Buffer flip() {limit = position;position = 0;mark = -1;return this;}

案例

        ByteBuffer hbb = ByteBuffer.allocate(1024);System.out.println(hbb.toString());hbb.flip();System.out.println(hbb.toString());

输出

java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=0 lim=0 cap=1024]

hasRemaining 是否有剩余

    public final boolean hasRemaining() {return position < limit;}

position < limit 代表有剩余,position = limit 代表空间已经满了

clear 清除

    public final Buffer clear() {position = 0;limit = capacity;mark = -1;return this;}

将buffer三个指针位置重置。

get

hbb

    final byte[] hb;    public byte get() {return hb[ix(nextGetIndex())];}

dbb

    public byte get() {return ((unsafe.getByte(ix(nextGetIndex()))));}

asReadOnlyBuffer 只读buffer

    public ByteBuffer asReadOnlyBuffer() {return new HeapByteBufferR(hb, this.markValue(), this.position(), this.limit(),this.capacity(), offset);}

buffer 案例1 基本操作读和写

创建5个容量的buffer,依次将i放进去,翻转buf,依次读出来。

public class byteBuffer02 {public static void main(String[] args) {ByteBuffer buffer = ByteBuffer.allocate(5);for (byte i = 0; i < buffer.capacity(); i++) {buffer.put(i);}buffer.flip();while (buffer.hasRemaining()) {System.out.println(buffer.get());}}
}

buffer 案例2 不同类型数据读写

public class ByteBuffer03 {public static void main(String[] args) {ByteBuffer bb = ByteBuffer.allocate(64);bb.putInt(100);bb.putLong(9);bb.putChar('a');bb.putShort((short) 4);bb.flip();System.out.println("----");System.out.println(bb.getInt());System.out.println(bb.getLong());System.out.println(bb.getChar());System.out.println(bb.getShort());}
}

buffer 案例3 只读 buffer

public class ByteBuffer04 {public static void main(String[] args) {ByteBuffer b1 = ByteBuffer.allocate(64);ByteBuffer b2 = b1.asReadOnlyBuffer();b1.putInt(5);b2.putInt(5);}
}

MappedByteBuffer

深入浅出java.nio.MappedByteBuffer

Channel 通道

实现
在这里插入图片描述
源码

public interface Channel extends Closeable {//是否开启public boolean isOpen();//关闭public void close() throws IOException;}

FileChannel

开启通道的几种方式

    static File file = new File("D://a.txt");

从 RandomAccessFile 中getChannel

        RandomAccessFile raf = new RandomAccessFile(file, "rw");FileChannel fc = raf.getChannel();

从 stream 中 getChannel

        FileOutputStream fos = new FileOutputStream(file);FileChannel fc2 = fos.getChannel();       

FileChannel.open

        FileChannel fc3 = FileChannel.open(null, null);

案例1

将 uuid 读出来

public class ReadFileUid {static File file = new File("D://a.txt");public static void main(String[] args) throws Exception {ByteBuffer bf = ByteBuffer.allocate(1024);try (RandomAccessFile raf = new RandomAccessFile(file, "rw");FileChannel fc = raf.getChannel()) {int read = fc.read(bf);System.out.println(read);System.out.println(bf);bf.flip();System.out.println(bf);byte[] bytes = new byte[bf.limit()];bf.get(bytes);System.out.println(bf);System.out.println(Arrays.toString(bytes));String str = new String(bytes, StandardCharsets.UTF_8);System.out.println(str);}}
}

输出

36
java.nio.HeapByteBuffer[pos=36 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=0 lim=36 cap=1024]
java.nio.HeapByteBuffer[pos=36 lim=36 cap=1024]
[54, 51, 51, 53, 98, 102, 53, 97, 45,
99, 57, 100, 54, 45, 52, 53, 51, 99,
45, 98, 57, 99, 98, 45, 102, 50, 52,
102, 56, 97, 54, 101, 98, 50, 99, 50]
6335bf5a-c9d6-453c-b9cb-f24f8a6eb2c2

案例2

将 uuid 写到文件中

public class WriteFileUid {static File file = new File("D://a.txt");public static void main(String[] args) throws Exception {ByteBuffer bf = ByteBuffer.allocate(1024);try (RandomAccessFile raf = new RandomAccessFile(file, "rw");FileChannel fc = raf.getChannel()) {String uuid = UUID.randomUUID().toString();System.out.println(uuid);byte[] bytes = uuid.getBytes(StandardCharsets.UTF_8);System.out.println(Arrays.toString(bytes));System.out.println(bf);bf.put(bytes);System.out.println(bf);bf.flip();System.out.println(bf);int write = fc.write(bf);System.out.println(write);}}
}
efdd8059-4f47-42e9-b9f9-aadd4a324309
[101, 102, 100, 100, 56, 48, 53, 57, 45, 52, 102, 52, 55,45, 52, 50, 101, 57, 45, 98, 57, 102, 57, 45, 97, 97,100, 100, 52, 97, 51, 50, 52, 51, 48, 57]
java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=36 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=0 lim=36 cap=1024]
36

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

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

相关文章

研究 | CT图像迭代重建算法研究进展

上次讲到我实现了一下代数迭代重建&#xff08;ART&#xff09;&#xff0c;到周六开会的时候才大概了解了我的研究方向应该是统计迭代重建&#xff0c;一下子就把我给搞懵了。按照书上的说法&#xff0c;统计迭代法是在发射型CT&#xff08;SPECT和PET&#xff09;中应用广泛&…

[附源码]计算机毕业设计勤工俭学管理小程序Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Docker学习4-常用命令之重要的容器命令

本文是Docker学习系列教程中的第四篇。本文是Docker常用命令中的重要命令。为什么说重要呢&#xff1f;因为这些命令&#xff0c;在以后开发过程中&#xff0c;会经常使用到。比如&#xff1a;怎么查看容器中运行的日志&#xff1f;怎么查看容器运行的进程&#xff1f;怎么导出…

【安全测试】渗透测试神器BurpSuite环境搭建

工欲善其事&#xff0c;必先利其器&#xff0c;要想更好的进行安全测试&#xff0c;就需要有一个趁手的工具&#xff0c;BurpSuite就是一个不错的选择&#xff0c;是广大安全测试工程师的必备工具&#xff0c;今天就带着大家把这个工具给装上&#xff0c;开启大家的安全测试之旅…

引擎入门 | Unity UI简介–第2部分(5)

本期我们继续为大家进行Unity UI简介&#xff08;第二部分&#xff09;的后续教程 本篇内容 9.设置动画对话框 文章末尾可免费获取教程源代码 本篇本篇Unity UI简介&#xff08;第二部分&#xff09;篇幅较长&#xff0c;分为八篇&#xff0c;本篇为第五篇。 9.设置动画对…

【信息检索与数据挖掘期末复习】(五)Language Model

什么是语言模型&#xff1f; 一个传统的语言生成模型可以用于识别或生成字符串 我们可以将有穷自动机看作是一种确定性的语言模型 基本模型&#xff1a;每一个文档都是通过一个像这样的自动机生成的&#xff0c;只不过这种自动机是有概率的 一种最简单的语言模型等价于一个…

纪念DedeCMS创始人IT柏拉图先生

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; IT柏拉图开发了DedeCMS&#xff0c;造福了千万站长&#xff0c;但却没有因为这套系统过上体面的生活。 &#xff08;图片取自IT柏拉图的新浪微博&#xff09; 1979年你出生了&#xff0c;比我大…

终于有人把Java面试高分Guide总结得如此系统,堪称傻瓜式笔记总结

纵观今年的技术招聘市场&#xff0c; Java依旧是当仁不让的霸主 &#xff01;即便遭受 Go等新兴语言不断冲击&#xff0c;依旧岿然不动。究其原因&#xff1a; Java有着极其成熟的生态&#xff0c;这个不用我多说&#xff1b;Java在 运维、可观测性、可监 控性方面都有着非常优…

Paper reading:Fine-Grained Head Pose Estimation Without Keypoints (CVPR2018)

Paper reading&#xff1a;Fine-Grained Head Pose Estimation Without Keypoints &#xff08;CVPR2018&#xff09; 一、 背景 为什么要读这篇论文&#xff0c;因为LZ之前要做头部姿态估计&#xff0c;看到一些传统的方法&#xff0c;都是先进行人脸检测&#xff0c;然后再…

Redis原理 - 对象的数据结构(SDS、Inset、Dict、ZipList、QuickList、SkipList、RedisObject)

Redis数据结构 1. SDS Redis 是用 C 语言写的&#xff0c;但是对于 Redis 的字符串&#xff0c;却不是 C 语言中的字符串&#xff08;即以空字符’\0’结尾的字符数组&#xff09;&#xff0c;它是自己构建了一种名为 简单动态字符串&#xff08;simple dynamic string,SDS&am…

实验7 数据库编程

第1关 定义一个名为PROC_COUNT的无参数存储过程 任务描述 定义一个名为PROC_COUNT的无参数存储过程&#xff0c;查询工程名称中含有“厂”字的工程数量&#xff0c;并调用该存储过程。 相关知识 1、工程项目表J由工程项目代码(JNO)、工程项目名(JNAME)、工程项目所在城市(CITY)…

Java ConcurrentHashMap 高并发安全实现原理解析

三、C13Map的字段定义 C13Map的字段定义 //最大容量 private static final int MAXIMUM_CAPACITY 1 << 30; //默认初始容量 private static final int DEFAULT_CAPACITY 16; //数组的最大容量,防止抛出OOM static final int MAX_ARRAY_SIZE Integer.MAX_VALUE -…

linux环境下,一步步教你命令行搭建自己的git服务器和客户端

前言&#xff1a; 先说下我的git服务器环境&#xff0c;git服务端的搭建我用的是阿里的ubantu云服务器&#xff0c;毕竟云服务器上可以在任何联网的电脑上访问嘛&#xff0c;方便。局域网也可以&#xff0c;svn和git这两种最常用的代码管理系统&#xff0c;在企业中基本…

LVGL自定义组件__页面指示器

前言 LVGL对硬件的要求非常低&#xff0c;使用其自带的组件能够搭建出精美的界面&#xff0c;动效也很棒。但是如过移植到Linux平台下&#xff0c;开发稍微复杂的应用项目&#xff0c;那些组件就远远不够用了。为此需要自己自定义一些组件&#xff0c;以方便实用。 效果 为此…

GitHub上架即下架,《分布式系统人人都是架构师》全彩笔记开源

又来给大家分享好书了&#xff1a;高翔龙老师的 《超大流量分布式系统架构解决方案&#xff1a;人人都是架构师2.0》&#xff0c;我在网上没找见开源的PDF版本所以分享一下&#xff01;小编会在文末附电子版免费方式。 高翔龙是谁&#xff1f; 云集基础架构负责人&#xff0c…

Verilog中 高位与低位

Verilog中信号定义位宽的一些问题 总是被Verilog中信号定义位宽的问题所困扰&#xff1a; wire[7:0] data1 和 wire[0:7] data1有什么不一样 wire[7:0] data2[3:0]、wire[7:0] data2[0:3]、wire[0:7] data2[3:0]、wire[0:7] data2[0:3]又分别有什么不一样&#xff1f; 今天下定…

【C++进阶】引用 函数提高

文章目录一 、引用1.1 引用的基本使用1.2 引用的注意事项1.3 引用做函数参数1.4 引用的本质 &#xff1a;指针的常量1.5 常量引用二、函数提高1 函数默认参数2 函数占位参数3 函数重载一 、引用 1.1 引用的基本使用 作用&#xff1a;给变量起别名 语法&#xff1a;数据类型 &a…

TC申请是否需要银行转账记录?

【TC申请是否需要银行转账记录&#xff1f;】 答案是毫无疑问的。 根据TE官网公开的文件CCS Certification Procedures V3.0 里面关于TC申请所需的文件指引E2.1.1f&#xff1a;&#xff08;如图&#xff09; 企业在申请与TE相关的认证项目&#xff08;例如GRS/RCS等等&#xf…

MySQL基础三问:底层逻辑、正在执行、日志观察

背景及目录&#xff1a; 经常面试会遇到且实际工作中也会应用到的三个场景&#xff1a; 一.mysql查询时的底层原理是什么&#xff1f; 二.如何查看正在执行的mysql语句&#xff1f; 三.如何观察mysql运行过程中的日志信息&#xff1f; - - - - - - - - - -分割线- - - - -…

「Redis」07 持久化操作(RDB、AOF)

笔记整理自【尚硅谷】Redis 6 入门到精通 超详细 教程 Redis——持久化操作&#xff08;RDB、AOF&#xff09; 1. RDB&#xff08;Redis DataBase&#xff09; 概述 RDB是什么 在指定的时间间隔内将内存中的数据集快照写入磁盘&#xff0c; 即 Snapshot 快照&#xff0c;恢…