java NIO ByteBuffer 学习

java NIO ByteBuffer 学习

ByteBuffer看过很多资料。看完很久没有用便忘记了,今天遇到了需要ByteBuffer的场景,就需要复习,于是便写点博客或者程序加深印象,下次直接使用不再需要复习资料。

  • ByteBuffer介绍

ByteBuffer的内部字段

  • 1.byte[] buff
    用来存贮字节数据的数组
  • 2.position
    当前读写操作的数据位置下标,读写会从这个位置开始,操作完成之后会更新下标的值。
  • 3.mark
    标记。一个临时变量。当调用mark()方法的时候,mark变量记录当前position的值。后续操作中有reset()方法调用的时候 会将postion回滚到mark的值。mark()与reset()配套使用。
  • 4.capacity
    容量。这个ByteBuffer的最大容量。 一般在初始化的时候,定义好了capacity;
 ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
 //以上代码初始化了一个byteBuffer,这个byteBuffer的初始化大小为1024
  • 5.limit
    限制。读写是不能超过该值。默认的情况下,写数据的时候limit==capacity,读数据的时候 limit == buffer中有效数据的长度.
    说明:0 <= mark <= position <= limit <= capacity, ByteBuffer中直接操作 limit和capacity,position的方法。

    /**
    *直接设置position
    **/
    public final Buffer position(int newPosition) {
        if ((newPosition > limit) || (newPosition < 0))
            throw new IllegalArgumentException();
        position = newPosition;
        if (mark > position) mark = -1;
        return this;
    }
    
    /*
    *直接设置limit的值
    */
    public final Buffer limit(int newLimit) {
        if ((newLimit > capacity) || (newLimit < 0))
            throw new IllegalArgumentException();
        limit = newLimit;
        if (position > limit) position = limit;
        if (mark > limit) mark = -1;
        return this;
    }

    除了以上两种方法可以改变postion和limit的值
    flip(),clear();


ByteBuffer的内部方法


  • 1.flip();
    原码如下:

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

    mark标志改为-1;limit改为position,即limit设置当前写入的数据位置。然后数据位置position设置为起始位置

  • 2.clear();
    原码如下:

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

    mark标志改为-1;数据位置position设置为起始位置,limit设置为缓冲区的容量大小。并非真的清空,如果上次读满,这次未读满,缓冲区就会存在上次处理的数据。判断是否还有可用数据:

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

    另外 compact()方法:
    作为抽象方法。在不同子类中有不同的实现。这里得说说ByteBuffer的子类
    DirectByteBuffer
    HeapByteBuffer
    由字面意思我们就可以看出
    DirectByteBuffer 是直接操作操作系统内存,HeapByteBuffer是操作堆内存。

     HeapByteBuffer(int cap, int lim) {            // package-private
    
        super(-1, 0, lim, cap, new byte[cap], 0);
        /*
        hb = new byte[cap];
        offset = 0;
        */
    }
    
    
    
    DirectByteBuffer(int cap) {                   // package-private
    
        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 {
            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 boundary
            address = base + ps - (base & (ps - 1));
        } else {
            address = base;
        }
        cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
        att = null;
    }
    

    在 HeapByteBuffer 中的 compact实现:

public ByteBuffer compact() {
    System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
    position(remaining());
    limit(capacity());
    return this;
}

该方法的作用是将 position 与 limit之间的数据复制到buffer的开始位置,复制后 position = limit -position,limit = capacity

但如果position 与limit 之间没有数据的话发,就不会进行复制

以下内容来自转载:
java NIO ByteBuffer 学习_第1张图片

https://blog.csdn.net/shuaiAWP/article/details/51915983
  

你可能感兴趣的:(java并发编程)