有没有一个支持动态增长并扩展java.nio.ByteBuffer的ByteBuffer实现?

3

我的代码中有一个java.nio.ByteBuffer:

最初的回答:

ByteBuffer bb = ByteBuffer.allocateDirect(1024);
... 

我希望能够替换一个新的ByteBuffer实现(即它必须扩展java.nio.ByteBuffer),以便在底层重新分配、复制和丢弃先前的小ByteBuffer,从而实现无缝动态增长。
我不能只有一个包装器,因为它必须是一个java.nio.ByteBuffer。
它应该像这样:
ByteBuffer bb = new MyImplementationOfByteBufferThatExtendsByteBuffer(1024);

有人见过或者做过这个吗?这是否可行?

只需注意,如果java.nio.ByteBuffer是一个接口而不是一个抽象类,那么实现起来就很容易。正如古语所说,如果想要灵活性,应该优先使用接口而不是抽象类

最初的回答:


可能是Growing ByteBuffer的重复问题。 - Nolequen
1
我认为这不是重复的问题,因为那个问题不需要bytebuffer扩展java.nio.ByteBuffer。所有给出的答案都是包装器。 - Eddie Bravo
ByteBuffer的所有构造函数都是包私有的。因此,可能不会有“干净”的解决方案... - Marco13
或者自己实现:https://github.com/wjtxyz/VarSizedByteBuffer - Yessy
2个回答

2
不,这是不存在的,也不能存在,否则就会违反ByteBuffer超类Buffer的约定:
缓冲区是特定原始类型元素的线性有限序列。除了其内容之外,缓冲区的基本属性是其容量、限制和位置: - 缓冲区的容量是它包含的元素数。缓冲区的容量从不为负且永远不会改变。
因此,如果允许"无缝动态增长",ByteBuffer将不再作为Buffer运行。这也适用于接口与抽象类:子类和接口实现都不应该打破在它们扩展的类中定义的不变量。毕竟,你假设的GrowingByteBuffer的消费者可能依赖于Buffer的固定容量来缓存对capacity()的单个调用,否则该调用将被定义为不发生变化。
将ByteBuffer定义为抽象类而不是接口的另一个推动因素是:支持缓冲区的内存被定义为必须是固定和连续的,这比更灵活的定义具有更高的性能。
那么,Buffer定义了一个可变的“limit”概念,其中一个最初分配的大缓冲区可能会受到人为限制。您可以使用此功能将大型缓冲区限制为从小开始增长,但增长不会是“无缝”的;它将受到您定义的原始缓冲区容量的限制。如果目标仅是连接较小的固定大小缓冲区,其中总体总大小是可预测的,则可以将它们作为较大缓冲区的一部分生成,使用 ByteBuffer.duplicate并设置“mark”和“limit”以限制可写区域。

1
我相信ByteBuffer有一个固定的容量是有意为之的。我鼓励你不要试图绕过它,认可并接受这个有目的的限制。如果你允许ByteBuffer增长,那么compact()将不再具有可预测的最大运行时间。你的缓冲区越大,压缩所需的时间就越长。我在我的基于NIO的套接字库中遇到了这个问题。我内部的缓冲区会增长以适应大量数据注入,结果是性能随着缓存的数据量而下降。例如,有人可能尝试一次性发送100MB的数据,因此我会将这些数据保存在一个100MB的ByteBuffer中。处理代码一次只能处理约32KB的数据,因此它会从缓冲区中获取32KB的数据,然后进行压缩。然后是另外32KB和另一个压缩。它将继续读取和压缩,直到缓冲区被排空。
每次压缩都是一个O(n)的操作,而我进行了O(n)次压缩,导致总运行时间为O(n2)。非常糟糕的消息。当缓冲区变得非常大以至于I/O请求开始超时时,我注意到了这个问题,因为I/O线程花费了所有的时间来压缩字节缓冲区。
解决方案:如果您想要动态缓冲区,请创建一个Queue<ByteBuffer>。队列可以增长并容纳无限数量的ByteBuffer,而每个缓冲区保持固定大小。这将使您的应用程序在不遇到O(n2)问题的情况下正确扩展。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接