java resizable方法_Java Resizable Array

Java Resizable Array

Java Resizable Array - GitHub Repository

Resizable Array Use Case

Resizable Array DesignExpand on Write

Keeping Track of Free Blocks

Freeing Arrays

Using the ResizableArrayBuffer

Creating a ResizableArrayBuffer

Obtaining a ResizableArray Instance

Writing to a ResizableArray

Reading From a ResizableArray

Freeing a ResizableArray

有时候我们为了快速便捷的读取数据,想把数据保存在单个连续的数组里。这就需要数组是可以调节大小的,或者是可以扩张的。但是在Java中数组的大小是不可以调节的。你必须亲自实现一个可调节大小的数组,在本文中我将展示如何实现这个数组。

Java Resizable Array-GitHub Repository

包含了三个classes和两个测试类

Resizable Array Use Case

想象下如果你有一个接受不同数据的Server,最小的数据4KB,大的1MB或者更大。

如果Server同一时间有1000K+的访问连接,我们需要知道要为数据提前分配多大的空间。我们不能仅仅只是分配一个最大的空间(1MB&16MB)为每个buffer。当有一千条连接访问Server时(100.000 × 1MB = 100GB),需要100GB的空间。

换一种思路,我们先从最小的信息开始处理,如果信息size超过了最小信息,那么我们重新分配一块空间并把原来的信息复制过去。如果信息又超过了现有的容量,那么再次分配并复制

使用这种策略,大多数信息将会使用最小buffer。这也就意味着Server的内存使用会变得非常高效,(100.000×4KB = 400MB),即使连接访问达到(1000.000 × 4KB = 4GB)。大多数Server也能hold住。

Resizable Array Design

resizable array 包含两个部分

ResizableArray

ResizableArrayBuffer

ResizableArrayBuffer包含一个单一,高容的数组。这个数组被分为三个部分。一个部分为small arrays,一个为medium size arrays 和 large array。

ResizableArray就表示单一,高容的数组,它的数据存储在ResizableArrayBuffer中的数组。

有图有真相

9ca519f8ea89849465a17af8d95829bb.png

为了在ResizableArrayBuffer中的large array为各个大小不一的message预留空间,我们需要保证array不会被任意大小的message填充满。例如,接受了大量的small mesages,并不会占用全部的内存,但是却会阻塞Server接受medium和large message。相似的,接受大量的large或medium message也不会占用所有的内存,但却会使得另外连个message type产生阻塞。

假如所有的message都是从small messages开始,如果大量的small arrays被耗尽,无论medium array或large array是否有空间,都不会分配新的array。但是如果将small arrays的大小设置的合理,这种情况发生的概率就会降低。

即便small message部分全部被占用了,small message还是有可能会grow为medium and large messages的。

Keeping Track of Fress Blocks

large array 在ResizableArrayBuffer中被分为三个部分,每个部分又被分为很多小块。每个小块在每个部分中有着相同的大小。

当所有的块在其所处的部分有着相同的大小时,它是很容易去跟踪那些使用着的块和没有使用的块。你可以使用一个queue(队列)来保存每个块的开始索引。对于每个部分都需要有这么一个queue(队列),一个queue(队列)去跟踪可用的small blocks,medium blocks 和 large blocks 同样是这样的。

Allocating a block from any of the sections can be accomplished simply by taking the next free block start index from the queue associated with the desired section. Freeing a block is done by putting the start index back into the corresponding queue.(能力有限)

Expand on Write

当你向array中写入数据时,Resizable array将会自己expand。如果你尝试向其中写入更多的数据,但是 array 没有多余的空间,它会被分配一个新的更大的 block 并且把原有的数据全部复制过去,之前的使用的block就free掉。

Freeing Arrays

一旦你获得了一个更大的array,你就应该释放掉原来的array,以便它可以存储别的message。

Using the ResizableArrayBuffer

我教你如何使用ResizableArrayBuffer

Creating a ResizableArrayBuffer

首先你必须创建一个ResizableArrayBuffer

1 int smallBlockSize = 4 * 1024;2 int mediumBlockSize = 128 * 1024;3 int largeBlockSize = 1024 * 1024;4

5 int smallBlockCount = 1024;6 int mediumBlockCount = 32;7 int largeBlockCount = 4;8

9 ResizableArrayBuffer arrayBuffer =

10 newResizableArrayBuffer(11 smallBlockSize , smallBlockCount,12 mediumBlockSize, mediumBlockCount,13 largeBlockSize, largeBlockCount);

This example creates a ResizableArrayBufferwith a small array size of 4KB, medium array size of 128KB and a larger array size of 1MB. The ResizableArrayBuffercontains space for 1024 small arrays (4MB in total), 32 medium arrays (4MB in total) and 4 large arrays (4MB in total) - for a full shared array size of 12MB.(不想翻了)

Obtaining a ResizableArray Instance

获得一个ResizableArray instance,调用ResizableArrayBuffer`s getArray()方法。

ResizableArray resizableArray = arrayBuffer.getArray();

这个例子会获得一个很小的ResizableArray(4KB)

Writing to a ResizableArray

你可以调用ResizableArray自己的write()方法。你可以重构它

1 ByteBuffer byteBuffer = ByteBuffer.allocate(1024);2

3 for(int i=0; i < 1024; i++){4 byteBuffer.put((byte) i);5 }6 byteBuffer.flip():7

8 int bytesCopied = resizableArray.write(byteBuffer);

这个例子将ByteBuffer中的数据copy到ResizableArray中的array(block),返回值是复制了多少个字节数。

一种情况是ByteBuffer中的数据大于ResizableArray的容量,那么ResizableArray将尝试expand自身的空间为了ByteBuffer中的数据。如果ResizableArray在expanding后不能包含所有的ByteBuffer数据,write()方法将会返回-1并且也不会复制data。

Reading From a ResizalbeArray

当你从ResizableArray读取数据时,你可以直接在所有ResizableArray实例共享的共享数组中读取。ResizableArray包含以下几个字段:

1 public byte[] sharedArray = null;2 public int offset = 0;3 public int capacity = 0;4 public int length = 0;

shareArray字段引用所有的ResizableArray实例中的共享array,这是保存在ResizableArrayBuffer中的内部array。

offset字段包含着共享array中的开始索引。

capacity字段包含ResizableArray实例中分配的共享数组中block的size。

length字段包含多少正在使用的block

去读取卸载ResizableArray中的数据时,是从shareArray[offset]到shareArray[offset+length-1]。

Freeing a ResizableArray

一旦你使用完了ResizableArray,你就要free它。仅需要调用ResizableArray中的free()方法即可。

resizableArray.free();

调用free()方法负责返回使用过的block到正确的queue,不管分配给ResizableArray中block的大小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值