[Netty笔记一]ByteBuf(一)

[Netty笔记一]ByteBuf(一)

Netty的ByteBuf很复杂,需要慢慢学习,先从java.nio.ByteBuffer对比看起。

一 JAVA NIO的ByteBuffer

ByteBuffer是个抽象类,通过静态方法allocate、allocateDirect分别分配heap buf和direct buf。HeapByteBuffer就是heap buf的具体实现类,DirectByteBuffer就是direct buf的具体实现类。而ByteBuffer继承自Buffer抽象类,ByteBuffer起了个承上启下的作用,分配具体类型的缓存,并对Buffer的功能进行复杂接口的封装。

1. Buffer抽象类

Buffer定义了基本操作逻辑。主要操作:

1) mark()

使用变量mark来表示,用于标记当前位置。可能的用法场景:从某个位置开始操作,但是不满足条件,需要回退。在这种场景下可以用mark()函数先标记其实位置,操作,不满足条件时,用reset()回退到mark()标记的位置。

2) position

position变量用于标示当前操作所处的位置。读写两个操作都用同一个变量position来指示当前操作的位置。没错,你没看错,是同一个变量来控制读取和写入。。。

3) flip()

​ flip操作,可以理解为一个开关,用于控制读写转换。如用put向缓存中写入了3个字节,此时position=3,可读取的字节为3;调用flip后,position=0,limit=3,意味着从0开始,可以读取3个字节。

4) limit和capacity

capacity就是缓存大小,一旦初始化,后续没法动态调整;limit就是当前缓存的数据量。

5) rewind()

将position清0,mark变量清掉。使用场景与flip类似,前提是需要自己准确设定limit。

2. ByteBuffer

ByteBuffer除了提供缓存的静态方法,还提供一下方法。

1) put() get()

put和get为抽象方法,put用于写入,get用于读取,就是上面Buffer中提到的读写操作。

2) slice()

切片。就是从缓存当前位置切割,而使用剩下的数据。当然,这个是数据是共享的,只是通过调整位置来实现这一功能。不过要说明的是,ByteBuffer使用offset这个变量来实现这一功能,而不是直接通过调整position来实现,即position还是原有的定义,但是用offset来调整缓存的起始位置(ix()函数)。

3) duplicate()

复制。这个操作数据也是共享的,只是重新包装了一下,也就是位置变量之类的不同。

3. 其它

从上面的介绍来看,JAVA NIO提供的ByteBuffer总体功能有限,尤其是读写转换需要flip这个操作,使用起来会比较无力,对于复杂的读写操作,还需要自己牢记各种位置来mark,reset,rewind。。。

二 ByteBuf

Netty与NIO的缓存有比较大的区别,简单概括如下:

1) 内部指针

上面提到NIO的Buffer使用一个position变量同时被读写操作使用,需要flip来转换读写模式,同时mark也只有一个变量; Netty的ByteBuf则使用readerIndex、writerIndex,标记位也有两个markedReaderIndex、markedWriterIndex,取消了limit,writerIndex就可以达成类似的作用;使用上最大的便利就是不需要flip来回转换了:-)。。。

2) 组合模式

​ CompositeByteBuf可以将多个ByteBuf组合在一起,但是实现了ByteBuf接口。也就是当组合多个ByteBuf时,不需要额外拷贝,却可以像使用ByteBuf一样,这个在协议编解码场景,尤其有用。这个也是NIO完全缺失的一个特性。

3) 池化

​ Netty提供了池化和非池化两种方式来获取ByteBuf实例。池化可以最大限度减少内存碎片,非池化与NIO方式一致,没有为内存管理做特殊处理。池化和非池化,与heap buf和direct buf是两个概念,heap与direct是内存分配方式,池化是对分配的内存做管理。同样,NIO也没有这个特性。

4) 内存追踪

​ Netty中有ReferenceCounted接口专门用于负责追踪内存使用。retain方法增加引用计数,release方法减少引用计数。该功能主要是针对direct内存。

5) 工具类

​ Netty提供了丰富的工具类,用于场常见的字符串处理以及其它功能。如ByteBufUtil工具类,定义了很多的工具方法,最常用的应该是hexDump,对于调试打印非常方便;还有ByteProcessor接口类,在遍历ByteBuf时也非常方便。

总结

刚开始接触Netty的时候,只是好奇大家都在说的高性能,简单的写了个demo,除了pipeline,没啥感觉(请原谅我的无知);直到看到了源码中给出的示例,才发现Netty的牛逼,可以用非常简单的代码来实现一个代理功能,这种代码实现上的优雅让我折服,准备花时间把Netty系统学习一下。本文是第一篇,后面继续。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章