JAVA NIO Buffer

所谓的输入,输出,就是把数据移除或移入缓冲区。

硬件不能直接访问用户控件(JVM)。

基于存储的硬件设备操控的是固定大小的数据块儿,用户请求的是任意大小的或非对齐的数据块儿。

虚拟内存:使用虚拟地址取代取代物理地址。

  1. 可以有多个虚拟地址指向同一个物理地址。
  2. 虚拟内存空间可以大于实际的硬件内存。

应用:直接内存使用--使用户空间虚拟地址和内核虚拟地址同时指向同一个物理地址,可以使硬件直接访问用户空间内存。

数据库等应用严重依赖文件锁定。

缓冲区:

缓冲区是包在一个对象内的基本数据类型数组。Buffer把关于数据内容和信息包含在一个对象中,并定义了一系列API。

信息提供操作属性:0<=mark<=position<=limit<=capicity

  1. 容量(Capicity):创建时设定,无法动态更改。
  2. 上界(Limit):现存元素计数。
  3. 位置(Position):下一个要被读取的元素位置。动态更新。
  4. 标记(Mark):备忘位置,mark()设定mark=position,reset()设定postion=mark。

插入“hello”之后:

Buffer类方法签名:

返回Buffer自身的一些方法可以直接级联调用。

创建只读缓存。例如ByteBuffer:

ByteBuffer bf = ByteBuffer.allocate(1024).asReadOnlyBuffer()

Flip():讲一个能够继续添加数据元素的填充状态的缓冲区翻转为一个准备读出元素的释放状态。

bf.flip() = bf.limit(bf.position()).position(0)

rewind():

bf.rewind() = bf.position(0)

缓冲区不是线程安全。

mark():Buffer是从当前位置开始向通道内输出内容的,如下,怎会输出‘ow’,position到6

reset()后,positon至mark位置。

两个具有相同元素的Buffer,只要剩余元素数量(从位置到上界)相同,就equals=true。

Buffer.get(byte[]):BufferUnderflowException;

当将一个buffer内容读入数组,buffer内容不足以填充数组时,会抛出此异常。因为需要指明可以读入的buffer内容长度。如下:

Buffer.get(byte[], 0, Buffer.remaining());

Buffer.put(byte[]):BufferUnderflowException;

当将数组元素写入buffer,buffer没有足够的空间时,会抛出此异常。

Buffer.wrap(byte[], int offset, int length):offset,length只是设置了初始化状态,并不是创建只占数组子集的缓冲区,缓冲区可以可以存取数组的全部范围。区别slice函数。

allocate(), wrap() 创建的缓冲区都是间接的,使用备份数组,可以获得数组的操作权。

Duplicate()复制缓冲区会创建一个新的Buffer对象,但是并不复制数据,原始缓冲区和副本会操作同样的数据元素。

Slice() 创建从原始缓冲区当前位置开始的新的缓冲区,容量是原始缓冲区的剩余容量,(limit-position),与原始缓冲区共享一段数据元素子序列。分割出来的子序列继承只读和直接属性。

每个基本的数据类型都是以连续的字节序列存储在内存中,多字节被存储在内存中的方式称为字节顺序(endian-ness)。如果数字数值的最高字节--big-end(大端)位于低位地址,那么系统就是大端字节顺序,反之小端字节顺序。

IP协议规定了使用大端的网络字节顺序概念。

通过ByteOrder.nativeOrder() 输出LITTLE_ENDIAN或者BIG_ENDIAN判断。

Java默认的字节序是大端序,系统无关性,ByteBuffer.order() 总是范围ByteOrder.BIG_ENDIAN。

只有字节缓冲区有资格参与IO操作,IO操作的目标区域必须是连续的字节序列。JVM中的数据字节数组可能存储不连续,切GC可能会对其进行移动。所以IO不能直接操作。

直接缓冲区用于与通道或固有IO例程交互,通过固有代码告知系统直接操作内存区域。

直接缓冲区=》通道

非直接缓冲区=》临时直接缓冲区=》IO=》临时直接缓冲区回收。

选择依据执行频率,高频脚本使用直接缓存区。

创建直接缓冲区是调用本地操作系统分配的内存,比基于JVM创建的基于堆栈的缓冲区更加耗费,所以也不会被回收管理。

先使其工作,再加快其运行。首先注重正确性。过早的优化是所有祸害的根源。

ByteBuffer.allocateDirect(),开辟直接内存。

视图缓冲区:

通过已有的缓冲区对象示例的工厂方法来创建。视图缓冲维护自己的属性、容量、位置、上界和标记,但是和原来的缓冲区共享数据元素。如,ByteBuffer类允许创建视图来将byte型缓冲数组转化为其它的原始类型,ByteBuffer.asLongBuffer()。为基础缓冲区的切分,基于基础缓冲区的位置和上界(position-limit)

如下,ByteBuffer.asCharBuffer():

ByteBuffer中的两个字节映射成CharBuffer中的一个字符,CharBuffer中的字节排序不可以再改变。

数据元素视图:

以多字节数据形式存取byte数据组,存取和转化:

从ByteBuffer的当前位置存取字节数据,根据缓冲区当前的有效字节数序,字节会被排列或打乱成原始的数据类型。

例如getInt(),从当前位置开始的四个字节会被包装成一个Int返回。如下:

映射缓冲区(MappedByteBufefer):

通过内存映射存取元素的字节缓冲区,直接存取内存,只能通过FileChannel类创建。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JVM之Parallel Scavenge收集器

    WindWant
  • JAVA NIO Scatter/Gather(矢量IO)

    数据从几个缓冲区顺序抽取并沿着通道发送,就好比全部缓冲区全部连接起来放入一个大的缓冲区进行发送,缓冲区本身不具备gather能力。

    WindWant
  • Consul 简介

    1、服务发现:一个客户端提供自己的服务,例如api服务,或者mysql服务,另一个客户端就可以利用Consul通过DNS或者http来发现这些服务的提供者。

    WindWant
  • Java NIO使用及原理分析(三)

    在上一篇文章中介绍了缓冲区内部对于状态变化的跟踪机制,而对于NIO中缓冲区来说,还有很多的内容值的学习,如缓冲区的分片与数据共享,只读缓冲区等。在本文中我们来看...

    用户6182664
  • Java NIO 缓冲区学习笔记

    Buffer其实就是是一个容器对象,它包含一些要写入或者刚读出的数据。在NIO中加入Buffer对象,体现了新库与原I/O的一个重要区别。在面向流的I/O中,您...

    哲洛不闹
  • Power Query中Buffer的用法

    缓冲区(Buffer)就是在内存中预留指定大小的存储空间用来对I/O(输入/输出)的数据做临时存储,这部分预留的内存空间叫缓冲区。

    逍遥之
  • NIO 之 Buffer 图解

    java404
  • 「高并发通信框架Netty4 源码解读(三)」NIO缓冲区Buffer详解

    一个Buffer对象是固定数量的数据的容器。其作用是一个存储器,或者分段运输区,在这里数据可被存储并在之后用于检索。缓冲区如我们在上一篇所讨论的那样被写满和释放...

    源码之路
  • 史上最强Java NIO入门:担心从入门到放弃的,请读这篇!

    本文原题“《NIO 入门》,作者为“Gregory M. Travis”,他是《JDK 1.4 Tutorial》等书籍的作者。

    JackJiang
  • 史上最强Java NIO入门:担心从入门到放弃的,请读这篇!

    本文原题“《NIO 入门》,作者为“Gregory M. Travis”,他是《JDK 1.4 Tutorial》等书籍的作者。

    JackJiang

扫码关注云+社区

领取腾讯云代金券