netty源码分析(六) - ByteBuf - 1结构

2020-10-14  本文已影响0人  进击的蚂蚁zzzliu

概述

netty使用ByteBuf缓冲区来对读写字节进行操作,所谓缓冲区就是可以作为一个字节容器存储字节,等到一定大小之后再交给CPU去处理,提升效率;
ByteBuf提供了强大的API及体系,相比JDK的ByteBuffer通过position和limit来控制读写,每次切换都需要调用flip方法,ByteBuf通过writerIndex和readerIndex来简化控制,使用简单;

ByteBuf

ByteBuf维护了两个索引:readerIndex(读索引)和writerIndex(写索引)

 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      |                   |     (CONTENT)    |                  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity

ByteBuf分类

ByteBuf.png

AbstractByteBuf

AbstractByteBuf是ByteBuf的骨架实现,包含各个读写索引,提供_get/_set方法让子类实现具体的字节操作逻辑;

//读索引
int readerIndex;
//写索引
int writerIndex;
//读标记
private int markedReaderIndex;
//写标记
private int markedWriterIndex;
//最大容量
private int maxCapacity;

以getInt()和readInt()为例,分析获取数据方法:

public int getInt(int index) {
    // 检查索引是否越界
    checkIndex(index, 4);   
    return _getInt(index);
}

public int readInt() {
    // 检查索引是否越界
    checkReadableBytes0(4);
    int v = _getInt(readerIndex);
    // 读索引右移
    readerIndex += 4;   
    return v;
}

protected abstract int _getInt(int index);  

可见readInt与getInt都是模板方法的模式,先对索引进行检查,然后将实际操作交给子类负责具体实现的_getInt()方法;两者的区别在于是否自动维护读索引,readInt将增加读索引,getInt则不会对索引产生任何影响。

以setInt()和writeInt()为例,分析写入数据方法

public ByteBuf setInt(int index, int value) {
    checkIndex(index, 4);
    _setInt(index, value);
    return this;
}

public ByteBuf writeInt(int value) {
    ensureAccessible();
    ensureWritable0(4);
    _setInt(writerIndex, value);
    writerIndex += 4;
    return this;
}

protected abstract void _setInt(int index, int value);

ByteBufAllocator(内存分配器)分类

ByteBufAllocator.png

ByteBuf结构分析到此结束,下一节详细讲解各中类型ByteBuf如何分配及重点方法实现

上一篇 下一篇

猜你喜欢

热点阅读