1. 堆缓冲区模式(Heap Buffer)
堆缓冲区模式又称为:支撑数组(backing array)。将数据存放在JVM的堆空间,通过将数据存储在数组中实现
Direct Buffer属于堆外分配的直接内存,不会占用堆的容量。适用于套接字传输过程,避免了数据从内部缓冲区拷贝到直接缓冲区的过程,性能较好
Composite Buffer是Netty特有的缓冲区。本质上类似于提供一个或多个ByteBuf的组合视图,可以根据需要添加和删除不同类型的ByteBuf。
代码:
1. discardReadBytes()效果 —– 将可读字节区域(CONTENT)[readerIndex, writerIndex)往前移动readerIndex位,同时修改读索引和写索引。
2. discardReadBytes()方法会移动可读字节区域内容(CONTENT)。如果频繁调用,会有多次数据复制开销,对性能有一定的影响
2. readerIndex(int) —– 设置readerIndex为固定的值
3. writerIndex(int) —– 设置writerIndex为固定的值
4. clear() —– 效果是: readerIndex=0, writerIndex(0)。不会清除内存
5. 调用clear()比调用discardReadBytes()轻量的多。仅仅重置readerIndex和writerIndex的值,不会拷贝任何内存,开销较小。
1. 最简单的方法 —– indexOf()
2. 利用ByteProcessor作为参数来查找某个指定的值。
代码:
1. duplicate()
2. slice()
3. slice(int, int)
4. Unpooled.unmodifiableBuffer(…)
5. Unpooled.wrappedBuffer(…)
6. order(ByteOrder)
7. readSlice(int)
理解
1. 上面的6中方法,都会返回一个新的ByteBuf实例,具有自己的读索引和写索引。但是,其内部存储是与原对象是共享的。这就是视图的概念
2. 请注意:如果你修改了这个新的ByteBuf实例的具体内容,那么对应的源实例也会被修改,因为其内部存储是共享的
3. 如果需要拷贝现有缓冲区的真实副本,请使用copy()或copy(int, int)方法。
4. 使用派生缓冲区,避免了复制内存的开销,有效提高程序的性能
代码:
1. get()和set()操作 —– 从给定的索引开始,并且保持索引不变
2. read()和write()操作 —– 从给定的索引开始,并且根据已经访问过的字节数对索引进行访问
3. 下图给出get()操作API,对于set()操作、read()操作和write操作可参考书籍或API
5.3.10 更多的操作
1. hasArray() —– 如果ByteBuf由一个字节数组支撑,则返回true。通俗的讲:ByteBuf是堆缓冲区模式,则代表其内部存储是由字节数组支撑的。如果还没理解,可参考5.2.2章节
2. array() —– 如果ByteBuf是由一个字节数组支撑泽返回数组,否则抛出UnsupportedOperationException异常。也就是,ByteBuf是堆缓冲区模式
1. ByteBufHolder是ByteBuf的容器,可以通过子类实现ByteBufHolder接口,根据自身需要添加自己需要的数据字段。可以用于自定义缓冲区类型扩展字段。
2. Netty提供了一个默认的实现DefaultByteBufHolder。
代码
public class CustomByteBufHolder extends DefaultByteBufHolder{
private String protocolName;
1. ctx.channel().alloc().buffer() —– 本质就是: ByteBufAllocator.DEFAULT
2. ByteBufAllocator.DEFAULT.buffer() —– 返回一个基于堆或者直接内存存储的Bytebuf。默认是堆内存
3. ByteBufAllocator.DEFAULT —– 有两种类型: UnpooledByteBufAllocator.DEFAULT(非池化)和PooledByteBufAllocator.DEFAULT(池化)。对于Java程序,默认使用PooledByteBufAllocator(池化)。对于安卓,默认使用UnpooledByteBufAllocator(非池化)
4. 可以通过BootStrap中的Config为每个Channel提供独立的ByteBufAllocator实例
解释:
1. 上图中的buffer()方法,返回一个基于堆或者直接内存存储的Bytebuf —– 缺省是堆内存。源码: AbstractByteBufAllocator() { this(false); }
2. ByteBufAllocator.DEFAULT —– 可能是池化,也可能是非池化。默认是池化(PooledByteBufAllocator.DEFAULT)
注意:
1. 上图的buffer()方法,返回一个未池化的基于堆内存存储的ByteBuf
2. wrappedBuffer() —– 创建一个视图,返回一个包装了给定数据的ByteBuf。非常实用
创建ByteBuf代码:
1. hexdump() —– 以十六进制的表示形式打印ByteBuf的内容。非常有价值
2. equals() —– 判断两个ByteBuf实例的相等性
1. 谁负责释放: 一般来说,是由最后访问(引用计数)对象的那一方来负责将它释放
2. buffer.release() —– 引用计数减1
3. buffer.retain() —– 引用计数加1
4. buffer.refCnt() —– 返回当前对象引用计数值
5. buffer.touch() —– 记录当前对象的访问位置,主要用于调试。
6. 引用计数并非仅对于直接缓冲区(direct Buffer)。ByteBuf的三种模式: 堆缓冲区(heap Buffer)、直接缓冲区(dirrect Buffer)和复合缓冲区(Composite Buffer)都使用了引用计数,某些时候需要程序员手动维护引用数值
代码:
2. ByteBuf的三种模式: 堆缓冲区(heap Buffer)、直接缓冲区(dirrect Buffer)和复合缓冲区(Composite Buffer)都使用了引用计数,某些时候需要程序员手动维护引用数值。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/219880.html原文链接:https://javaforall.net
