netty-Buffer基本

抛开其他,先来了解一下Buffer

七种Buffer

type buffer
byte ByteBuffer
char CharBuffer
short ShortBuffre
int IntBuffre
float FloatBuffer
double DoubleBuffer
long LongBuffer
boolean -

对于八种基本类型,除了boolean都有对应的Buffer

Buffer的几个属性

Buffer的话,说白了就是个单一类型的容器。

  • capacity

容器的上限,超过就存不下了。

  • limit

已存储的,或可存储的最后一位。

初始化时,或者clear初始化操作后,总是挪到最后一位,也就是limit = capacity

当翻转flip后,指向最后一个元素位置。所以limit <= capacity

  • position

我们写入put和读取get操作时,读取的就是position位置的元素。

不过在写入或读取之后,它会自动跳转到下一个位置,也就是+1

不过,它的极限也就是limit了,也就是position <= limit

  • mark

不算做是很重要的属性,但是又额外功能。

主要目的就是标记一个元素,reset复位后就可以回到原来的位置了。

所以mark <= position <= limit <= capacity

Buffer的几个行为

  • allocate:创建
  • capacity:获取上限值
  • position:调整position
  • mark:标记mark,默认-1
  • limit:获取limit
  • put:放入一个值,position自动加一
  • get:读取一个值,position自动加一
  • clear:``position=0, limit=capacity`
  • fliplimit=position, position=0,状态翻转
  • remaininglimit -position,判断是否还有更多元素
  • hasRemainingposition < limit,同上

理解和实现

基于简单的理解而实现,仅仅基本操作,不涉及更多内容。

public class IntBuffer {
    private int capacity;
    private int limit;;
    private int position;
    private int mark;
    private int [] arr;
    private IntBuffer(int capacity){
        this.arr = new int[capacity];
        this.capacity = capacity;
        this.limit = this.capacity;
        this.position = 0;
        this.mark = -1;
    }
    public static IntBuffer allocate(int capacity){
        return new IntBuffer(capacity);
    }
    public int capacity(){
        return this.capacity;
    }
    public IntBuffer position(int position){
        this.position = position;
        return this;
    }
    public IntBuffer limit(int limit) {
        this.limit = limit;
        return this;
    }
    public IntBuffer mark(){
        this.mark = this.position;
        return this;
    }
    public IntBuffer reset(){
        this.position = this.mark;
        return this;
    }
    public IntBuffer clear(){
        this.position = 0;;
        this.limit = this.capacity;
        return this;
    }
    public IntBuffer flip(){
        this.limit = position;
        this.position = 0;
        return this;
    }
    public IntBuffer put(int value){
        if(this.position < this.limit){
            this.arr[position++] = value;
        }
        return this;
    }
    public int get() throws Exception {
        if(this.position < this.limit){
            return this.arr[this.position++];
        }
        throw new Exception("last index");
    }
    public boolean hasRemaining(){
        return position < limit;
    }
    public int remaining(){
        return limit - position;
    }
}

简单逻辑实现,为了清晰,更多判断未加上。

  • 测试
public class Main {
    public static void main(String[] args) throws Exception {
        IntBuffer buffer = IntBuffer.allocate(10);
        Random random = new SecureRandom();
        while(buffer.hasRemaining()){
            buffer.put(random.nextInt(20));
        }
        buffer.flip();
        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }
    }
}

ByteBuffer的归一

底层的存储,其实都是字节,也就是说,不论何种类型,底层都可以看做是ByteBuffer

ByteBuffer以一种固定的编解码读取字节数据,就成了各种特定的SomethingBuffer

所以,ByteBuffer可以算作是可以存取任意类型基本数据类型的归一化容器。

public class Main {
    public static void main(String[] args) throws Exception {
        ByteBuffer buffer = ByteBuffer.allocate(256);
        int lastIndex = buffer.position();
        int nowIndex = buffer.position();
        buffer.putInt(1);
        nowIndex = buffer.position();
        show("int : " + (nowIndex - lastIndex));
        lastIndex = nowIndex;
        buffer.putDouble(2.0d);
        nowIndex = buffer.position();
        show("double : " + (nowIndex - lastIndex));
        lastIndex = nowIndex;
        buffer.putFloat(3f);
        nowIndex = buffer.position();
        show("float : " + (nowIndex - lastIndex));
        lastIndex = nowIndex;
        buffer.putLong(4l);
        nowIndex = buffer.position();
        show("long : " + (nowIndex - lastIndex));
        lastIndex = nowIndex;
        buffer.putShort((short)5);
        nowIndex = buffer.position();
        show("short : " + (nowIndex - lastIndex));
        lastIndex = nowIndex;
        buffer.put((byte)6);
        nowIndex = buffer.position();
        show("byte : " + (nowIndex - lastIndex));
        lastIndex = nowIndex;
        buffer.putChar('a');
        nowIndex = buffer.position();
        show("char : " + (nowIndex - lastIndex));
        buffer.flip();
        show(buffer.getInt());
        show(buffer.getDouble());
        show(buffer.getFloat());
        show(buffer.getLong());
        show(buffer.getShort());
        show(buffer.get());
        show(buffer.getChar());

    }
    public static void show(Object obj){
        System.out.println(obj);
    }
}

netty-Buffer基本_第1张图片

可以看到我们利用ByteBuffer不仅可以针对进行写入,还能针对进行读取。

但是类型一定要对应,否则会解码失败,从而报错。

而且,顺便复习一下基础占据空间大小。

byte:1byte, 8bit

char:2byte,16bit

short:2byte,16bit

int:4byte,32bit

float:4byte,32bit

double:8byte,64bit

long:8byte,64bit

slice

public class Main {
    public static void main(String[] args) throws Exception {
        IntBuffer buffer = IntBuffer.allocate(5);
        for(int i = 0;i < buffer.capacity(); i++ ){
            buffer.put(i);
        }
        buffer.position(1);
        buffer.limit(4);
        IntBuffer sliceBuffer = buffer.slice();
        while(sliceBuffer.hasRemaining()){
            show("slice : " + sliceBuffer.get());
        }
        show("====================");
        buffer.clear();
        while(buffer.hasRemaining()){
            show("source : " + buffer.get());
        }
    }
    public static void show(Object obj){
        System.out.println(obj);
    }
}

netty-Buffer基本_第2张图片

slice返回的是buffer [ p o s i t i o n , l i m i t ) [position,limit) [position,limit)区间的元素,同时,两者共用的是同一块空间,同一个存储结构。

public class Main {
    public static void main(String[] args) throws Exception {
        IntBuffer buffer = IntBuffer.allocate(5);
        for(int i = 0;i < buffer.capacity(); i++ ){
            buffer.put(i);
        }
        buffer.position(1);
        buffer.limit(4);
        IntBuffer sliceBuffer = buffer.slice();
        while(sliceBuffer.hasRemaining()){
            show("slice : " + sliceBuffer.get());
        }
        show("====================");
        buffer.clear();
        while(buffer.hasRemaining()){
            show("source : " + buffer.get());
        }
    }
    public static void show(Object obj){
        System.out.println(obj);
    }
}

netty-Buffer基本_第3张图片

如果还需要警惕什么,就是clear只是:position=0,limit-capacity,并没有真正的删除数据。

对于linux中的一些数据删除,也是如此,只是取消了文件标记,但是数据仍然存在。

asReadOnlyBuffer

public class Main {
    public static void main(String[] args) throws Exception {
        IntBuffer buffer = IntBuffer.allocate(2);
        buffer.put(1);
        buffer.put(2);
        IntBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
        buffer.put(1,9);
//        readOnlyBuffer.clear();
        while(readOnlyBuffer.hasRemaining()){
            show("read:" + readOnlyBuffer.get());
        }
    }
    public static void show(Object obj){
        System.out.println(obj);
    }
}

运行是没有结果的,但是把注释打开

readOnleBuffer.clear();

在这里插入图片描述

readOnly就不用说了,为什么不clear就没有结果。

因为返回的readOnlyBufferslice不太一样,它会复制此时bufferposition和其他属性。

例子中已经读取到结尾,所以就不会出现结果了。

除了position状态保留的差异,也可以看到,也共享同一块内存空间,会受到原有buffer写操作的影响。

你可能感兴趣的:(netty)