第三节 netty前传-NIO中缓冲buffer-01

Buffers

缓冲区(Buffers)本质上是一个可以写入数据的内存块,然后可以读取。 这个内存块包含在NIO Buffer对象中,该对象提供了一组api,这样可以方便用户更轻松地使用内存块。

在NIO中已实现的buffer类中继承Buffer这个抽象类

public abstract class Buffer {
    // Cached unsafe-access object
    static final Unsafe UNSAFE = Unsafe.getUnsafe();
    /**
     * The characteristics of Spliterators that traverse and split elements
     * maintained in Buffers.
     */
    static final int SPLITERATOR_CHARACTERISTICS =
        Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;

    // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;
    private int position = 0;
    private int limit;
    private int capacity;
//略。。。
}

其他具体的实现方式,根据不同的需求实现例如 ByteBuffer底层使用的为byte数组 CharBuffer使用char数组 DirectByteBuffer使用直接内存,这里通过从抽象类中的Unsafe 类分配直接内存使用。

  • 缓冲的基本用法:下面是最基本的四步
  1. 向buffer写入数据
  2. 调用buffer.flip() 方法反转
  3. 读取buffer中的数据
  4. 调用buffer.clear() 或者buffer.compact()清楚

当数据写入缓冲区时,缓冲区会跟踪写入的数据量(在buffer对象中有position 会跟踪写入点)。 一旦需要读取数据,就需要使用flip() 方法调用将缓冲区从写入模式切换到读模式。 在读模式下,缓冲区允许读取已经写入缓冲区的所有数据。一旦读完所有数据,需要清除缓冲区,以便再次写入。 可以通过两种方式执行:调用clear()或调用compact() 方法。 clear() 方法清除整个缓冲区。 compact()方法仅清除已读取的数据。 任何还没读的数据都会移动到缓冲区的开头,接下来写入时,就会在这些未读数据之后写入。 下面用一个简单的例子来说明

public class ReadFile {
    public static void main(String[] args){
        readFile();
    }
    public static void readFile(){
        try(RandomAccessFile randomAccessFile =
                    new RandomAccessFile("F:\\data\\test.txt","rw")){
            //获取连接通道
            FileChannel fileChannel = randomAccessFile.getChannel();
            //初始化一个缓冲区,大小为1024byte
            ByteBuffer buf = ByteBuffer.allocate(1024);
            //fileChannel.read(buf)从通道中读取文件的数据放入缓冲区,返回结构为读取的字节数
            //注意:这个方法会记录读取的位置,所以后续读取不会从头开始读取
            int bytesRead = fileChannel.read(buf);
            System.out.println(bytesRead);
            //读取到数据
            while(bytesRead != -1)
            {
                //反转后为可以读取缓冲中的数据
                buf.flip();
                while(buf.hasRemaining())//position < limit;表示可读
                {
                    //读取
                    System.out.print((char)buf.get());
                }
                //没有可读数据后,清除已读数据,从未读数据之后开始写入
                buf.compact();
                //开始继续读取
                bytesRead = fileChannel.read(buf);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

说明Buffer 中的Capacity, Position 和Limit之间的关系

如下图分别表示写入和读取操作的buffer

图片.png

  • Capacity 缓冲区具有一定的固定大小,也称为“容量”。 表示缓冲区的大小,也是buffer所能存储的最大容量
  • Position 写操作: 在数据写入缓冲区的时候,可以选择在某个位置执行此写入操作。 如果写入时没有选择相应的位置,会默认从最初位置0开始写入,每当一个字节,字符或者整数等等写入缓冲区时,position会自动被指向缓冲区中的下一个单元为了下次插入数据。 位置最大可以变为容量 -1。为-1时表示已经写满了,不可再写入。 读操作: 从缓冲区读取数据时,也可以从指定的位置开始读取数据。 当缓冲区从写入模式翻转到读取模式时(调用flip方法),位置position将重置为0.。同理,当从缓冲区读取数据时,将从position位置开始读取数据,并将自动将position移动到下一个要读取的位置。
  • Limit 写模式: limit的作用是限制写入缓冲区的数据量。写入时等于Capacity大小 读模式:缓冲区翻转为读取模式时,限制意味着可以从数据中读取的数据量的限制。 所以,当Buffer翻转到读取模式时,limit会被设置为写模式的写入位置。 换句话说,就是可以读取写入的字节数(限制设置为写入的字节数,由位置标记)。

关于Buffer中方法下一节详解

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java 成神之路

NIO 之 Channel

376130
来自专栏逆向技术

16位汇编语言第二讲系统调用原理,以及各个寄存器详解

   16位汇编语言第二讲系统调用原理,以及各个寄存器详解 昨天已将简单的写了一下汇编代码,并且执行了第一个显示到屏幕的helloworld 问题?   hel...

24400
来自专栏微服务生态

淘宝Tedis组件究竟是个啥(一)

淘宝的Tedis组件究竟是个啥呢?可能有一些朋友没有听过这个名字,有一些朋友会经常使用,那么今天我就来和大家深入分析一下,它的使用和原理。

12220
来自专栏FD的专栏

一步步理解python的异步IO

看到越来越多的大佬都在使用python的异步IO,协程等概念来实现高效的IO处理过程,可是我对这些概念还不太懂,就学习了一下。 因为是初学者,在理解上有很多不到...

18320
来自专栏智能大石头

STM32/GD32上内存堆栈溢出探测研究

无数次遭受堆栈溢出折磨,随着系统变得复杂,故障点越来越难以查找! 主要溢出情况如下: 1,一般RAM最后两块空间是堆Heap和栈Stack,堆从下往上用,栈从上...

26970
来自专栏一名合格java开发的自我修养

(代码篇)从基础文件IO说起虚拟内存,内存文件映射,零拷贝

JAVA虚拟机内部便会调用OS底层的 read()系统调用完成操作,在调用 in.read()的时候就是从内核缓冲区直接返回数据了。

8420
来自专栏cnblogs

knockoutjs 上自己实现的flux

在knockoutjs 上实现 Flux 单向数据流 状态机,主要解决多个组件之间对数据的耦合问题。 一、其实简单 flux的设计理念和实现方案,很大程度上人借...

24480
来自专栏开发技术

shiro源码篇 - shiro的session的查询、刷新、过期与删除,你值得拥有

    老公酷爱网络游戏,老婆无奈,只得告诫他:你玩就玩了,但是千万不可以在游戏里找老婆,不然,哼哼。。。     老公嘴角露出了微笑:放心吧亲爱的,我绝对不会...

40920
来自专栏YG小书屋

ES-Spark连接ES后,ES Client节点流量打满分析

72630
来自专栏高爽的专栏

Hession反序列化导致CPU占用飙高

背景 今天发布一个线上服务,暂且称之为O,发布完后,依赖O服务的2个服务C和W大量Time报警,并且这两个服务的CPU占用都飙到了40%左右,平时只有10%的样...

42100

扫码关注云+社区

领取腾讯云代金券