首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Netty精粹之玩转NIO缓冲区(1)

Netty精粹之玩转NIO缓冲区(1)

摘要: 在JAVA NIO相关的组件中,ByteBuffer是除了Selector、Channel之外的另一个很重要的组件,它是直接和Channel打交道的缓冲区,通常场景或是从ByteBuffer写入Channel,或是从Channel读入Buffer;而在Netty中,被精心设计的ByteBuf则是Netty贯穿整个开发过程中的核心缓冲区,那么他们俩有什么区别呢?Netty对于缓冲区的设计对于高性能应用又带来了哪些值得借鉴的思路呢?本文在介绍ByteBuffer和ByteBuf基本概念的基础之上对两者进行对比,进而扩展介绍Netty中的ByteBuf大家族。
在JAVA NIO相关的组件中,ByteBuffer是除了Selector、Channel之外的另一个很重要的组件,它是直接和Channel打交道的缓冲区,通常场景或是从ByteBuffer写入Channel,或是从Channel读入Buffer;而在Netty中,被精心设计的ByteBuf则是Netty贯穿整个开发过程中的核心缓冲区,那么他们俩有什么区别呢?Netty对于缓冲区的设计对于高性能应用又带来了哪些值得借鉴的思路呢?本文在介绍ByteBuffer和ByteBuf基本概念的基础之上对两者进行对比,进而扩展介绍Netty中的ByteBuf大家族。

JAVA NIO之ByteBuffer
JAVA NIO中,Channel作为通往具有I/O操作属性的实体的抽象,这里的I/O操作通常指readding/writing,而具有I/O操作属性的实体比如I/O设备、文件、网络套接字等等。光有Channel可不行,我们必须为他增加readding/writing的特性,因此JAVA NIO基于Channel扩展WritableByteChannel和ReadableByteChannel接口。由于本文的重点是ByteBuffer,因此我们对于Channel的设计就看到这里,因为有了WritableByteChannel和ReadableByteChannel之后,我们就可以对ByteBuffer进行操作啦,看看他们提供的两个接口:
1
2
<code class="hljs java"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public<span class="hljs-function"> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">int<span class="hljs-function"> <span class="hljs-title"><span class="hljs-function"><span class="hljs-title">read<span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(ByteBuffer dst)<span class="hljs-function"> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws<span class="hljs-function"> IOException;
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public<span class="hljs-function"> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">int<span class="hljs-function"> <span class="hljs-title"><span class="hljs-function"><span class="hljs-title">write<span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(ByteBuffer src)<span class="hljs-function"> <span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws<span class="hljs-function"> IOException;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>



从上面的接口我们可以看到Channel和ByteBuffer之间发生的两个基本行为,即readding/writing。无论是对文件(FileChannel)还是对网络(SocketChannel)的读写,他们都会去实现这两个基本行为。好了,我们已经从总体上认识ByteBuffer在JAVA NIO所处的位置和担当的角色了,下面我们继续深入一点认识ByteBuffer。
ByteBuffer有四个重要的属性,分别为:mark、position、limit、capacity,和两个重要方法分别为:flip和clear。ByteBuffer的底层存储结构对于堆内存和直接内存分别表现为堆上的一个byte[]对象和直接内存上分配的一块内存区域。既然是一块内存区域,那么我们就可以对其进行基于字节的读和写,而ByteBuffer的四个int类型的属性则是指向这块区域的指针:
  • position:读写指针,代表当前读或写操作的位置,这个值总是小于等于limit的。
  • mark:在使用ByteBuffer的过程中,如果想要记住当前的position,则会将当前的position值给mark,让需要恢复的时候,再将mark的值给position。
  • capacity:代表这块内存区域的大小。
  • limit:初始的Buffer中,limit和capacity的值是相等的,通常在clear操作和flip操作的时候会对这个值进行操作,在clear操作的时候会将这个值和capacity的值设置为相等,当flip的时候会将当前的position的值给limit,我们可以总结在写的时候,limit的值代表最大的可写位置,在读的时候,limit的值代表最大的可读位置。clear是为了写作准备、flip是为了读做准备。

返回列表