Java NIO核心原理

原创
2022/01/07 17:13
阅读数 154

NIO Buffer

简介

NIO Buffer 是一个数组内存块,与普通内存块不同的是,其提供的一系列的方法来操作内存块中的数据 在NIO中,有8种缓冲区类:ByteBuffer CharBuffer DoubleBuffer FloatBuffer IntBuffer LongBuffer shortBuffer 以及 MappedBuffer 前7种对应7种基本数据类型,MappedBuffer是一种专门用于内存映射的ByteBuffer子类 注:Buffer是一个线程安全类

属性及方法

属性position limit capacity 及allocate方法

/**
 * 在构建IntBuffer对象时,使用IntBuffer的 allocate()方法,并分配内存大小
 * 缓冲区在新建时处于写模式
 * position: 此时可写入的位置
 * limit: 最大上限,默认为可写上限(使用flip()后变成最大可读上限(5))
 * capacity: 缓冲区容量
 */
private void useAllocate() {
    intBuffer = IntBuffer.allocate(20);
    logger.info("--------------after allocate---------------");
    logger.info("position: " + intBuffer.position());//0
    logger.info("limit: " + intBuffer.limit());//20
    logger.info("capacity: " + intBuffer.capacity());//20
}

put方法

/**
 * put()方法:向缓冲区中写入内容
 * 每写入一个 int 型数据,position+1
 */
private void usePut() {
    intBuffer = IntBuffer.allocate(20);
    for (int i = 0; i < 5; i++) {
        intBuffer.put(i);
    }
    logger.info("--------------after put---------------");
    logger.info("position: " + intBuffer.position());//5
    logger.info("limit: " + intBuffer.limit());//20
    logger.info("capacity: " + intBuffer.capacity());//20
}

Filp方法

/**
 * flip()方法进行翻转
 * 此时参数发生变化:
 * position:变成读的起始位置(0)
 * limit:读的最大限制(5)
 * capacity: 缓冲区容量保持不变(20)
 */
private void useFlip() {
    intBuffer = IntBuffer.allocate(20);
    for (int i = 0; i < 5; i++) {
        intBuffer.put(i);
    }
    intBuffer.flip();
    logger.info("--------------after flip---------------");
    logger.info("position: " + intBuffer.position());//0
    logger.info("limit: " + intBuffer.limit());//5
    logger.info("capacity: " + intBuffer.capacity());//20
}

get方法

/**
 * 在使用 filp() 方法后,intBuffer的写模式变成了读模式
 * 使用get()可以获取到 intBuffer 的单个值
 * 注:get()的默认参数是 position,每 get一个值:position+1;但是 get(index) 是获取 index 处的值,position 不会改变
 * get获取值时,int这个数据依然存在于intBuffer,不会被拿走,只是 position 发生了变化
 */
private void useGet() {
    intBuffer = IntBuffer.allocate(20);
    for (int i = 0; i < 5; i++) {
        intBuffer.put(i);
    }
    intBuffer.flip();
    List<Integer> result = new ArrayList<Integer>();
    for (int i = 0; i < 2; i++) {
        result.add(intBuffer.get());
    }
    logger.info("--------------after get 2 int---------------");
    logger.info("result: " + result);//[0,1]
    logger.info("position: " + intBuffer.position());//2
    logger.info("limit: " + intBuffer.limit());//5
    logger.info("capacity: " + intBuffer.capacity());//20

    int num3 = intBuffer.get(0);
    logger.info("--------------after get index  int---------------");
    logger.info("num3: " + num3);//1
    logger.info("position: " + intBuffer.position());//2
    logger.info("limit: " + intBuffer.limit());//5
    logger.info("capacity: " + intBuffer.capacity());//20

    List<Integer> result2 = new ArrayList<Integer>();
    for (int i = 0; i < 3; i++) {
        result2.add(intBuffer.get());
    }
    logger.info("--------------after get next 2 int---------------");
    logger.info("result2: " + result2);//[2,3,4]
    logger.info("position: " + intBuffer.position());//5
    logger.info("limit: " + intBuffer.limit());//5
    logger.info("capacity: " + intBuffer.capacity());//20
}

rewind

/**
 * rewind()
 * (1)position重置为0
 * (2)mark被清理,之前的临时位置全部被清理
 * 注:在读模式下使用rewind(),变化的仅仅是position,表示从0开始读取,数据量没发生改变
 *    但是在写模式下使用rewind(),从零开始重新写,之前写的数据被清理
 */
private void useRewind(){
    intBuffer = IntBuffer.allocate(20);
    for (int i = 0; i < 5; i++) {
        intBuffer.put(i);
    }
    intBuffer.rewind();
    intBuffer.put(5);
    logger.info("position: " + intBuffer.position());//1
    logger.info("limit: " + intBuffer.limit());//20
    logger.info("capacity: " + intBuffer.capacity());//20
    intBuffer.flip();
    logger.info("position: " + intBuffer.position());//0
    logger.info("limit: " + intBuffer.limit());//1
    logger.info("capacity: " + intBuffer.capacity());//20
    intBuffer.rewind();
    logger.info("position: " + intBuffer.position());//0
    logger.info("limit: " + intBuffer.limit());//1
    logger.info("capacity: " + intBuffer.capacity());//20
}

mark

/**
 * mark:标记当前 position 的位置
 * reset:恢复 position 为 mark 的位置
 */
private void useMark(){
    intBuffer = IntBuffer.allocate(20);
    for (int i = 0; i < 5; i++) {
        intBuffer.put(i);
    }
    intBuffer.flip();
    List<Integer> result = new ArrayList<Integer>();
    for(int i = 0;i<5;i++){
        result.add(intBuffer.get());
        //这里已经取到了i=2的值,position=3
        if(i==2)
            intBuffer.mark();
    }
    intBuffer.reset();
    logger.info("position: " + intBuffer.position());//3
    Integer result2 = intBuffer.get();
    logger.info("result: "+result);
    logger.info("result2: "+result2);
}

clear

/**
 * clear():将读模式变为写模式,position=0,limit=capacity
 *
 */
private void useClear(){
    intBuffer = IntBuffer.allocate(20);
    for (int i = 0; i < 5; i++) {
        intBuffer.put(i);
    }
    intBuffer.flip();
    intBuffer.clear();
    intBuffer.put(10);
    int i = intBuffer.get(0);
    logger.info(String.valueOf(i));
}
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部