字节

时间:2020-01-09 10:35:41  来源:igfitidea点击:

Mem Ops Bytes类表示字节数组中的字节序列。它可以是共享字节数组中的字节序列,可以从字节分配器BytesAllocatorAutoDefrag或者BytesAllocatorManualDefrag中的一个获得,也可以是通过Java new运算符创建的字节数组。

为了避免用"字节"实例将Java堆弄成碎片,"字节"类被设计为从ObjectPool获得。因此,在将其引用的字节序列释放回分配给它们的字节分配器之后,可以将"字节"对象返回到"对象池"。

创建一个字节对象池

为了有效地使用"字节"类,我们应该创建一个" BytesAllocatorAutoDefrag",一个" BytesFactory"和一个" ObjectPool"。看起来是这样的:

BytesAllocatorAutoDefrag byteArrayAllocator = new BytesAllocatorAutoDefrag(new byte[1024 * 1024]);

BytesFactory bytesFactory = new BytesFactory(byteArrayAllocator);

ObjectPool<Bytes> objectPool = new ObjectPool<Bytes>(16,bytesFactory);

获取字节实例

要从ObjectPool中获取一个Bytes实例,我们只需调用ObjectPoolinstance()方法即可。这是一个从ObjectPool中获取字节实例的示例:

Bytes bytes = objectPool.instance();

分配字节序列

一旦从ObjectPool中获得了一个byte实例,就需要从BytesAllocatorAutoDefrag中分配一个字节序列。这是如何通过Bytes实例从ByteAllocatorAutoDefrag中分配字节序列的方法:

bytes.allocate(1024);

这个例子从ByteAllocatorAutoDefrag分配1024个字节。

可用字节

完成字节序列和" Bytes"实例后,我们需要再次释放字节序列和" Bytes"实例。我们可以通过调用Bytes``free()方法来实现。调用free()可以将Bytes实例释放回ObjectPool,将分配的字节释放给BytesAllocatorAutoDefrag。这是一个如何释放一个"字节"实例(包括它已分配的字节序列)的示例:

bytes.free();

字节字段

"字节"对象具有多个字段,可用于访问和使用"字节"对象表示的已分配字节序列。以下各节将介绍这些字段中的每个字段。

数据

" data"" Bytes"字段是对其中分配了字节序列的字节数组的引用。我们需要此参考,以便从分配的字节序列读取字节或者将字节写入分配的字节序列。这是一个例子:

byte value = bytes.data[someIndex];

bytes.data[someIndex] = 123;

startIndex

" startIndex""字节"字段包含由" data"字段引用的字节数组中的索引,在该数组中我们分配的字节序列开始。 " startIndex"字段包含该字节序列的第一个字节的索引。

长度

"字节"长度字段包含此"字节"对象表示的已分配字节序列的字节长度。

endIndex

" endIndex"字节字段包含分配的字节序列中最后一个字节之后的第一个索引。换句话说,由" endIndex"引用的字节不是字节序列的一部分,而是在它之前的字节。

" endIndex"等于" startIndex" +" length"。

同样," endIndex"将等于在此" Bytes"实例表示的字节序列之后立即分配的下一个字节序列的" startIndex"。

writeIndex

" writeIndex""字节"字段是在将字节写入分配的字节序列中时可以使用的索引。 writeIndex可以用来跟踪已经写入字节序列的字节数。同样,如果我们没有在字节序列中使用所有分配的字节,那么writeIndex可以跟踪实际写入字节序列中的字节数。

例如,假设我们必须将服务器的响应写回到客户端。我们知道响应永远不会超过1 MB,因此我们分配了1 MB的字节序列来保存响应。响应可能最终只需要例如38 KB,因此只有1 MB分配的字节序列中的这38 KB应该写回客户端。

然后,可以使用writeIndex字段来跟踪写入字节序列的字节。在上面的示例中,writeIndex将指向写入的38 KB字节之后的第一个字节。因此,要写回客户端的字节是从" startIndex"到(包括)" startIndex"到但不包括" writeIndex"的字节。换句话说,writeIndex类似于endIndex,只是写入的实际字节,而不是整个分配的字节序列。

readIndex

在读取实际写入分配的字节序列的字节时,可以使用" readIndex"字节字段。例如,如果将38 KB写入一个1 MB的分配序列中,则仅应再次读取分配序列的前38 KB。因此,在将响应发送回客户端时,我们将不得不从字节序列中读取这些38 KB并将它们写入网络套接字。如果无法一次读取所有字节,则可以使用readIndex来跟踪实际读取的字节数。

用例示例

在本节中,我将尝试为我们提供一些直观的用例示例,这些示例展示了如何使用Bytes类及其字段。这些用例实际上在使用" Bytes"类的方式上非常相似,即使它们做的是不同的事情。

接收和处理邮件

假设代码在服务器上运行,该服务器接收来自客户端的消息。当消息到达时,我们需要先将其存储在内存中,然后再对其进行处理,然后还需要对其进行处理。

首先,从共享字节数组开始,我们可以从中分配一个字节序列来存储传入的消息:

其次,从此共享字节数组中分配一个字节序列,该字节序列足够大以处理可接受的消息大小限制内的任何消息:

第三,将传入消息写入分配的字节序列中,同时前进writeIndex

第四,我们开始按分配的字节顺序处理消息,并随着处理越来越多的消息而前进readIndex

向客户发送回复

假设代码在服务器上运行,该服务器接收来自客户端的消息。处理完一条消息后,我们可能需要将响应发送回客户端。

首先,从共享字节数组开始,我们可以从中分配字节序列以将响应生成到其中,然后再将其发送回客户端:

其次,我们分配一个足够大的字节序列,以容纳任何可接受的响应消息大小限制内的响应:

第三,将响应消息生成为分配的字节序列,并在生成响应的同时推进writeIndex

第四,我们需要阅读生成的响应消息并将其发送回客户端。在读取并发送回生成的响应时,我们将前进readIndex