NIO三大组件之Buffer

什么是Buffer

Buffer(这里并不是特指Buffer类)是一个存储数据的容器,与数组类似(其实底层依旧是用数组的结构来存储数据),但不同的是,Buffer对象提供了一组更有效的方法去进行写入和读取的交替访问

Buffer类的特性

线程安全性

Buffer是线程不安全的,所以如果有多于一个线程去访问,那么需要手动加上同步操作

关键属性

capacity

是Buffer对象的能容纳的最大的元素个数(类似于数组的长度,但不一定是字节数组),不能为负,不能改变

limit

是第一个不能够被读或者被写的元素的位置(即能够被读和写的最大元素个数),要小于等于capacity
例如,在默认情况下limit=capacity,当capacity=10时,limit=10说明有索引0-9是可以访问的,也可以把limit理解为可以访问的元素的个数

position

是当前可以读取或者写入的元素的位置,要小于等于limit
在写入模式时,position初始为0,每有一个数据写入,则后移一位,最大值为limit-1
比如limit限制为10,则可以访问的索引为0-9共十个数,那么当position=9时是可写的,但当position=10时,就不可写了;
在读入模式时,position也是默认从零开始,但是由于调用flip()时会把position赋值给limit,所以position<=limit
例如当写入模式已经写入了index为9的元素,position此时为10,读状态时limit也为10

mark

可以暂时存储所需要的position的值,方便以后回到此位置,与其名字一样,起到标记的作用
0 <= mark <= position <= limit <= capacity

关键方法

flip

用于将写模式转换为读模式

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

clean

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

可以看出来,虽然名字叫做clean,但却没有真的去清除数据,只是改变了position和limit而已,却在事实上与清除数据有同样的效果,同时将读模式转换为写模式

compact

这个方法也可以把读模式变成写模式

reset

此方法把position恢复到mark的位置上

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

rewind

表示将之前的数据再读一次

其实这几个方法主要都是limit,position与mark这三个变量的值的转换

分类

所有的xxxBuffer类都继承了Buffer类,有各种原生类的buffer,其中byte类型的buffer又根据字符编码分为多种,但所有这些类都是抽象类或者不能直接从外部访问的类
而我们所使用的类一般都是以direct或者heap开头的实现类.这也是allocate()方法的返回值
这里以ByteBuffer源码为例

 public static ByteBuffer allocateDirect(int capacity) {
        return new DirectByteBuffer(capacity);
    }
public static ByteBuffer allocate(int capacity) {
        if (capacity < 0)
            throw new IllegalArgumentException();
        return new HeapByteBuffer(capacity, capacity);
    }

问题

Java NIO中是怎么判断一个buffer是读模式还是写模式的呢?

posted @ 2021-03-08 19:22  茕祇  阅读(107)  评论(0编辑  收藏  举报