【Java8源码分析】NIO包-Buffer类:ByteBuffer与HeapByteBuffer(一)

转载请注明出处:http://blog.csdn.net/linxdcn/article/details/72896616


1 概述

Java NIO 由以下几个核心部分组成:

  • Buffer
  • Channel
  • Selectors



相关类的使用方法可以参考Java NIO 系列教程,写的通俗易懂。

本文主要从源码方面分析一下Buffer类


2 Buffer类

Buffer类是一个抽象类,所有的XxxBuffer均继承此类。Buffer类的作用跟BufferedReaderBufferedInputStream类中的缓冲区作用是一样的。只不过线程Buffer独立出来,而且添加了更多的功能。

2.1 构造函数

public abstract class Buffer {

    private int mark = -1;
    private int position = 0;
    private int limit;
    private int capacity;

    // 在 direct buffers 中使用
    long address;

    Buffer(int mark, int pos, int lim, int cap) {
        if (cap < 0)
            throw new IllegalArgumentException("Negative capacity: " + cap);
        this.capacity = cap;
        limit(lim);
        position(pos);
        if (mark >= 0) {
            if (mark > pos)
                throw new IllegalArgumentException("mark > position: ("
                                                   + mark + " > " + pos + ")");
            this.mark = mark;
        }
    }
}

各属性变量的含义如下:

  • mark:初始值为-1,用于备份当前的position
  • position:初始值为0。position表示当前可以写入或读取数据的位置。当写入或读取一个数据后, position向前移动到下一个位置。
  • limit:
    • 写模式下,limit表示最多能往Buffer里写多少数据,等于capacity值。
    • 读模式下,limit表示最多可以读取多少数据。
  • capacity:缓存数组大小



2.2 主要方法

//返回容量
public final int capacity() {
    return capacity;
}

// 返回当前位置
public final int position() {
    return position;
}

//返回临界值
public final int limit() {
    return limit;
}

//记录当前位置
public final Buffer mark() {
    mark = position;
    return this;
}

//恢复到之前记录位置
public final Buffer reset() {
    int m = mark;
    if (m < 0)
        throw new InvalidMarkException();
    position = m;
    return this;
}

//清除缓冲区,即恢复变量的初始位置,但不清除缓冲区中的内容
public final Buffer clear() {
    position = 0;
    limit = capacity;
    mark = -1;
    return this;
}

//由写模式转为读模式
public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
}

//重置position为0,从头读写数据或读数据
public final Buffer rewind() {
    position = 0;
    mark = -1;
    return this;
}

3 ByteBuffer类

Java NIO 有以下Buffer类型

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer
  • MappedByteBuffer

其中MappedByteBuffer的实现比较特殊,其余各对应一种基础数据类型的缓冲区,实现原理是差不多的,下面以ByteBuffer为例介绍。

ByteBuffer也是一个抽象类,它的实现类有HeapByteBuffer和DirectByteBuffer两种。

  • HeapByteBuffer:是在jvm虚拟机的堆上申请内存空间
  • DirectByteBuffer:是直接在物理内存中申请内存空间

3.1 Buffer的分配

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

// 堆上面的分配
public static ByteBuffer allocate(int capacity) {
    if (capacity < 0)
        throw new IllegalArgumentException();
    return new HeapByteBuffer(capacity, capacity);
}

// 直接在物理内存上分配
public static ByteBuffer allocateDirect(int capacity) {
    return new DirectByteBuffer(capacity);
}

3.2 ByteBuffer的读写

从ByteBuffer中读写数据有两种方式(其余Buffer类也一样):

  • 通过Channel类的readwrite函数从Buffer中读写(后续Channel中介绍)
  • ByteBuffer的getput函数
public abstract byte get();

public abstract byte get(int index);

public abstract ByteBuffer put(byte b);

public abstract ByteBuffer put(int index, byte b);

3.2 Compact函数

ByteBuffer类比基类Buffer多了Compact函数,compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。

public abstract ByteBuffer compact();

3.3 HeapByteBuffer子类

HeapByteBuffer是ByteBuffer的实现子类,内部是通过byte数组实现在堆上的缓冲区,其余的getputcompact函数均通过数组下标操作实现,比较简单,源码就不列了。

protected final byte[] hb;

HeapByteBuffer(int cap, int lim) {  

    super(-1, 0, lim, cap, new byte[cap], 0);

}

HeapByteBuffer(byte[] buf, int off, int len) {

    super(-1, off, off + len, buf.length, buf, 0);

}

3.4 DirectByteBuffer子类

DirectByteBuffer是在jvm堆外直接申请一块空间,其把文件映射到该内存空间中,与MappedByteBuffer较为类似,在特大文件的读写方面效率非常高。由于比较特殊,将在下一篇详细介绍。

(未完,待续)


参考

http://ifeve.com/java-nio-all/


转载请注明出处:http://blog.csdn.net/linxdcn/article/details/72896616

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值