先思考一个问题:假设要设计一个池,我们要考虑哪些事情?
- 池要实现的功能?怎么实现?
- 池的可配置性?
带着这些问题,看看fesco的源码。
看一下fesco里面pool的继承结构
pool
|--BasePool
|
--BitmapPool
|
--GenericByteArrayPool
|
...
第一个问题:要实现的功能Pool类
V get(int size); //从池里面获取资源
void release(V value);//把不用的资源放回池
第二个问题:配置参数PoolParams类
public final int maxSizeHardCap;//硬上线
public final int maxSizeSoftCap;//软上线
public final SparseIntArray bucketSizes;// key bucketSize value maxLength
public final int minBucketSize;
public final int maxBucketSize;
public final int maxNumThreads;
看一下这几个参数的意义:
maxSizeHardCap:最大软上限,当池达到这个限制,池尝试释放空间,直到池的size小于软上限,或者剩余的空间为0
maxSizeSoftCap:最大硬上限,当池的大小超过硬上线,分配空间失败,并抛出PoolSizeViolationException异常
minBucketSize:最小的bucket大小,代表吃中的bucket最小size,用来保证所有的bucket持有的元素的size小于等于这个值。
maxBucketSize:最大的bucket大小,代表池中的bucket的最大的size,用来约束所有的bucket只允许元素小于或者等于这个值,如果超过这个值,会抛出异常。
maxNumThreads:最大可以访问这个池的线程的数量
bucketSizes:bucket数量,池配置了一系列固定大小的bucket。bucketSizes代表要创建各个bucket的size。此外,每个bucket规定了一个maxLength,用来限制bucket中的已经使用和未使用的元素的数量的总和。maxLength是个软上限,不会导致异常。它简单的用来控制释放的路径。当bucket大小是预先指定的,仍然可以池请求非标准尺寸,这种情况简单的当做 alloc/free 请求处理,并且值不会被池所持有。如果这个参数为空,pool将按需创建bucket
看一下Bucket是什么?
好吧,翻译一下doc
Bucket是BasePool的构成成分。池通过一系列的bucket持有它的空闲的值,每个bucket代表一系列的相同的size的值。每个bucket持有一系列的空闲的值。当池收到一个指定大小的get()请求的时候,池找到合适的bucket,返回给池的get()。当bucket空闲的列表没有空闲的时候,从空闲列表里面返回一个entry,并从空闲列表里面移除。类似的当一个value通过调用release释放到池里面,池定位合适的bucket,并且把value返回给bucket的空闲列表。bucket持有当前正在使用的item的数量。换句话说,就是bucket中的values现在被调用者使用着,但是不在空闲列表里面。bucket中的变量:length = mInUseCount + freelist size。maxLength变量代表这个bucket能增长到的最大值,这个值被池用来决定是否要释放values到bucket。
Bucket类:
通过
LinkedList
实现空闲列表
final Queue mFreeList;
mFreeList = new LinkedList();//get()
通过调用pop()
,并把使用计数mInUseLength++
release()
,只是简单