netty ByteBuf

原理简介:

1、从存储方式上,ByteBuf分为:HeapByteBuf和DirectByteBuf

HeapByteBuf是用byte数组格式来存储数据,在JVM内部开辟缓冲区,在数据操作前先把数据复制到byte数组再进行处理。因为中间增加了一层数据复制操作,会有一定的性能损耗。DirectByteBuf是使用java.nio.ByteBuffer来存储数据。利用java.nio.ByteBuffer是借助于JVM调用操作系统的底层通信函数,直接操作直接缓冲区可以减少中间缓冲区的复制操作,进而提供程序性能。

2、从空间初始化方式上来分,ByteBuf分为:缓存方式分配和非缓存方式分配。

空间分配工具类:PooledByteBufAllocator和UnpooledByteBufAllocator,其中UnpooledByteBufAllocator在外又封装了一个类Unpooled。

ByteBuf方法说明:

1、capacity()方法和capacity(newCapacity)

  无参时返回现有容量大小,有参数时设置新的容量大小。ByteBuf在这里做了优化,自动扩容优化

 private void ensureWritable0(int minWritableBytes) {
        if (minWritableBytes <= writableBytes()) {
            return;
        }

        if (minWritableBytes > maxCapacity - writerIndex) {
            throw new IndexOutOfBoundsException(String.format(
                    "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
                    writerIndex, minWritableBytes, maxCapacity, this));
        }

        // Normalize the current capacity to the power of 2.
        //计算新的容量,新的容量=当前容量*2 再取2^n 最接近当前容量*2的数值
        int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);

        // Adjust to the new capacity.
        // 设置ByteBuf新的容量
        capacity(newCapacity);
    }

 2、readableBytes()和readBytes(obj);

 readableBytes()返回当前可读的字节数:从readIndex到结尾的字节数。一般用于读取数据前进行数据完整性的判断。

   readBytes()读取数据到指定的obj变量中(还有其他参数)。

3、writableBytes()和maxWritableBytes()

writableBytes()是返回当前capacity可写入的字节数是多少;

maxWritableBytes()是返回ByteBuf创建时的maxCapacity可写入的字节数是多少

4、markReaderIndex()和resetReaderIndex()

markReaderIndex()把当前的readerIndex赋值到markReaderIndex中。

resetReaderIndex()重设readerIndex,把markIndex赋值到readerIndex。

这两个方法和readableBytes()、readBytes()结合使用可以完成数据的读取操作

5、markWriterIndex()和resetWriterIndex()

   markWriterIndex()方法是把当前writeIndex赋值到markWriteIndex中。

   resetWriterIndex()是把writeIndex设置为markWriteIndex的值。

6、writeBytes()

写数据函数,把数据吸入到ByteBuf中。

一般在写数据时和markWriterIndex()和resetWriterIndex()结合使用

7、clear()

清空ByteBuf,同时把readerIndex、markReaderIndex、writeIndex、markWriteIndex等设置为0

ByteBuf和ByteBuffer

在java.nio.ByteBuffer有capacity、position、limit、mark四种概念,除了容量不会改变以外,position、limit和mark在读写时都会发生改变,并且在读操作前要调用flip()方法重设position和limit才可以正确读出写入的数据。

而在netty的ByteBuf中,封装时重新定义了readerIndex和writeIndex,在读写时只是操作对应的标志位,开发者在使用当中读写时不用关心position、limit、mark,也不用执行flip()方法就可以很方便的读写操作。

   java.nio.Bytebuffer读写实例:

   ByteBuffer buf = ByteBuffer.allocate(10);

   buf.put(xxx);//写完毕转读取时

   buf.flip();//必须调用,否则读取的数据不正确

   buf.get(xxx);

   而使用netty的ByteBuf时不需要关心这些指针,如:

   ByteBuf buf = xxx;//生成新的ByteBuf

   byte writeData[] = {...};

   buf.writeBytes(writeData);//写入数据

   byte readData[] = new byte[11];

   buf.readBytes(readData);//不用其他操作,可直接读取

   通过上面的示例可以看出,netty的ByteBuf使用起来更方便

猜你喜欢

转载自hpgary.iteye.com/blog/2384153