NIO学习01Buffer

一、Buffer的定义

  • 用于特定原始类型数据的容器。其已知直接子类有:
    ByteBufferCharBufferDoubleBufferFloatBufferIntBufferLongBufferShortBuffer

  • 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。

  • Java NIO中的Buffer可用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的。// need an example

  • 缓冲区是特定原始类型的元素的线性有限序列。

  • 缓冲区不能安全地被多个并发线程使用。 如果一个缓冲区被多个线程使用,则应该通过适当的同步来控制对缓冲区的访问

二、基本属性

capacity

作为一个内存块,Buffer有一个固定的大小值,代表了缓冲区最大可写入的元素数量

position

下标,初始的position值为0,position表示当前的位置。相对读写(读写方法分为相对以及绝对两种类型,后面介绍)都从该位置开始。每次读写,position都会移动到下一个Buffer单元。position最大可为capacity – 1(下标从0开始,对应capacity个元素)

有多个方法都会对position重新赋值,最直接的方式

    /**
     * 对position进行赋值,如果新值小于mark,那么mark值将会被舍弃重新赋值为默认值-1
     */
    public final Buffer position(int newPosition) {
        if ((newPosition > limit) || (newPosition < 0))
            throw new IllegalArgumentException();
        position = newPosition;
        if (mark > position) mark = -1;
        return this;
    }

当调用filp()方法将Buffer从写模式切换到读模式,position会被重置为0

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

limit

在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit始终等于Buffer的capacity。

当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)

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

mark

标记,调用mark()函数会将mark设为当前的position值

    public final Buffer mark() {
        mark = position;
        return this;
    }

通常与reset()方法结合使用,来实现状态的恢复

    public final Buffer reset() {
        int m = mark;
        if (m < 0)
            throw new InvalidMarkException();
        position = m;
        return this;
    }

这几个变量之间存在关系 0 <= mark <= position <= limit <= capacity

三、Buffer中读模式和写模式的切换

写模式

从position位置开始(假如Buffer中已存在元素,则position不为0),最大限制为limit,此时limit等于capacity,每次写入一个数据后,position指针会跟着往下移动

写模式转换为读模式

调用flip()方法,从写模式切换到读模式时,position重置为0,从第一个元素开始开始读,最多可读元素个数limit等于读模式下的position值,即已写入的元素个数。

读模式切换为写模式

  • 如果一次性读完了所有数据,使用clear()函数将position指针指向0,limit等于capacity
    /**
     * Clears this buffer.  The position is set to zero, the limit is set to
     * the capacity, and the mark is discarded.
     */
    public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }
  • 如果一次不读完所有数据,留下了一个空间没有读取,使用compact()函数将没有读取的数据拷贝到顶端去,limit指针指向第一个可写入元素的空位置,limit重新指向capacity

不会画图,相关文章参考https://blog.csdn.net/Funny_Ma/article/details/103534022

四、Buffer的分配

要想获得一个Buffer对象首先要进行分配。 每一个Buffer类都有一个allocate方法

ByteBuffer buf = ByteBuffer.allocate(48);
CharBuffer buf = CharBuffer.allocate(1024);

五、读写数据

  1. 所有Buffer子类都定义了两类get/put方法(可选择性实现),相对的get/put方法是从当前position进行操作,每次操作都会对position进行变更,而绝对的get/put方法需要参数指定下标,从指定位置进行操作,不会更改position。如ByteBuffer中的定义
  /**
     * Relative <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
     * 注意,这里是可选实现
     * <p> Writes the given byte into this buffer at the current
     * position, and then increments the position. </p>
     *
     */
    public abstract ByteBuffer put(byte b);

    /**
     * Absolute <i>get</i> method.  Reads the byte at the given index.
     */
    public abstract byte get(int index);
  1. 通过通道读入缓冲区,以及从缓冲区写入到通道中
int bytesRead = inChannel.read(buf); //read into buffer.
int bytesWritten = inChannel.write(buf); //write into buffer.

其他相关API在了解第二点中的基本属性后,查看源码很好理解,这里就不一一介绍了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值