NIO揭秘-2

Buffer Internals(Buffer的内部构造)

    大纲:这一节中,我们将看到NIO的buffer中的两个重要的部分:状态变量和存取方法。

    状态变量是上一节中提到的“内部计数系统”的关键,随着每次读写操作,状态变量都在发生变化。通过记录和追踪这些变化,buffer有能力在内部管理其自身的一些资源。

    当你从channel中读取数据的时候,数据已经在buffer中了。在一些情况下,你可以将这个buffer直接的写到另一个channel中,但是通常,你希望看看这些数据。这可以通过get()方法来优雅的实现,同样的,当你想往buffer中放入数据时,你也可是使用put()方法。

    在这一节中,你将学到NIO中一些关于状态变量和存取方法。在起初看来NIO的内部计数系统很复杂,但你却可以很快的看到它在内部为你做了很多事情。你可能习惯与手写账簿--使用字节数组和下标变量--已经在NIO内部被处理了。

状态变量

    在任何时候,buffer中有三个变量可以明确的表示buffer的状态。

  •     position
  •     limit
  •     capacity

    这三个变量追踪和记录buffer的状态和包含的数据,我们马上来详细的解剖这三个变量,并且看看他们是如何使用于典型的读写进程的。为了举例的方便,我们假设正在从一个input channel中复制数据到output channel中。

    Position:

    你可能会知道buffer实际上是一个优化了的数组,当你从channel中读入数据时,你将数据读入到底层的数组中。这个position变量保存这你写入了多少数据。更精确的说,它指定了底层数组使用的下一个下标。因此,当你从一个channel中读入了3个字节的数据后,buffer的position就将被设置为3,标识着数组的第四个元素。

    同样的,当你从一个buffer中读入数据写到另一个channel中时,这个position变量保存着你从buffer中取出了多少数据。更精确的说,它指定了你从数组元素中读取的下一个下标。因此,如果你从buffer中读取了5byte的数据写入到channel中,buffer的position将被设置为5,也标识着数组中的第六个元素。

    Limit

    limit变量指定了还剩多少数据可以取得(在将数据从buffer中写入到channel的情况下)或者还有多少空位可以存放元素(在从一个channel中读入数据到buffer的情况下)。position总是小于或者等于limit。

    Capacity

    capacity指定了buffer中最多可以存放多少数据。实际上,他是底层数组的大小,或者至少是我们允许使用的底层数组的大小。

    图示:

    我们从一个新创建的buffer开始,为了演示的方便,我们假设buffer的capacity只有8个字节,现在buffer的状态如下:

   

    回忆一下limit不可能比capacity大,并且在这种情况下,其值也为8.我们将其也指在数组的末尾。

此时position的值为0,如果我们从别处读入数据到buffer中,则下一个字节所存放的位置就是下标0表示的位置,如果我们从buffer中写出数据,则下一个读出的数据的下标也为0所代表的位置,position的位置如下:

由于capacity没有发生改变,所以在接下来的讨论中忽略capacity这个值。

第一次读:

现在我们准备在我们新创建的buffer上进行读/写操作。我们开始从input channel中读入一些数据到buffer中,第一次取得3个字节,他们都被放入到以position开始的数组下标中,经过这次读操作后,position值增至3,下面是图示:

当然,limit值没有发生改变。

第二次读,我们从input channel中读入2字节的数据到buffer中,这两字节数据也存放在以position开始的数组下标中,同时position又增加了2.如下图示:

此时limit的值同样没有发生变化。

The flip

现在我们准备将数据从buffer写回到output channel中,在我们进行此项操作之前,我们必须调用flip()方法,这个方法做了两件重要的事情:

  • 1.他设置limit为position的值。
  • 2.他将position还原为0

上一张图片显示的是flip()之前的状态,下图显示的是调用flip()之后的状态:

现在我们已经准备好了将数据从buffer中写回到channel中了,position已经被重置为0了,表明着下一次读取的数据的下标为0,并且limit也已经设置为原来的position,意味着我们可以读入的数据的总数。

第一次写:

在我们的第一次写中,我们从buffer中取出了4个字节的数据并且将他们写回到了output channel中,这样position的值就变为了4,同样limit的值没有发生变化,如下图:

第二次写:

现在我们还有两字节的数据可以被写出,limit的值为5,position的值不能超过5,所以最后一次只能读入一个数据写回到output channel中,现在position的值为5,limit的值没有发生变化,如下图:

clear()方法:

最后一步我们调用了buffer的clear方法,这个方法重置了buffer以便让他重新接受数据,clear()做了两件主要的事情:

  • 1.设置limit的值为capacity
  • 2.设置position为0

下图表明了调用clear()方法之后的状态:

现在buffer可以接受新数据了。

下一节我们讲述buffer中一些方法的基本使用。

转载于:https://my.oschina.net/zhangya/blog/30485

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值