您的位置:首页 > 理论基础 > 数据结构算法

guava cache 存储的数据结构 --- 2

2016-01-27 17:36 676 查看
注: maxWeight 是缓存数超出设置的数量时就回收最近没有使用的活使用次数少的.

segment数组的初始化 : (先分为几个小段,get(key)时,根据key的hash定位到他是哪一个段内,提高查询效率)

先计算出分配hash段的个数(segment数组的个数)

计算每个segment初始化缓存的数量

为每个segment分配出合适的最大缓存数

根据数组的个数创建segment

public LocalCache( ...)  {
int segmentShift = 0;
int segmentCount = 1;
//个数< concurrencyLevel & (没有设置回收超出数 || 个数*20 <=  回收超出数)
while (segmentCount < concurrencyLevel && (maxWeight <0 || segmentCount * 20 <= maxWeight)) {
++segmentShift;
segmentCount <<= 1; //相当于segmentCount = segmentCount*2
}
//创建好总共分为几个hash段
this.segments = new Segment[segmentCount];

//计算每个hash段内的缓存数先初始化几个空对象
int segmentSize = 1;
int segmentCapacity = initialCapacity / segmentCount;
if (segmentCapacity * segmentCount < initialCapacity) {
++segmentCapacity;
}
while (segmentSize < segmentCapacity) {
segmentSize <<= 1;
}
//创建hash段
List<Integer> arr = getSegment();
int index = 0;
for(Integer i : arr ) {
this.segments[index++] =
createSegment(segmentSize, i,builder.getStatsCounterSupplier().get());
}

//以下两个和通过hash定位到segment有关
this.segmentShift = 32 - segmentShift;
segmentMask = segmentCount - 1;
}
//为每个hash段内分配最大缓存数
private List<Integer> getSegment() {
List<Integer> arr = new ArrayList<Integer>();
long maxSegmentWeight = maxWeight / segmentCount + 1;
long remainder = maxWeight % segmentCount;
for (int i = 0; i < this.segments.length; ++i) {
//限制缓存数时,为每个hash段内的限制数分配下
if(maxWeight >=0 ) {
if (i == remainder) {
maxSegmentWeight--;
arr.add(maxSegmentWeight);
}else
arr.add(-1);
}
return arr ;
}


AtomicReferenceArray{ReferenceEntry{K, V>> table

segment里有个AtomicReferenceArray{ReferenceEntry{K, V>>,这个是个数组,即存放数据的。

这个是再根据key的hashcode计算出索引, 找出ReferenceEntry{K, V>。这个table是被volatile修饰的,直接从主存读出写入的,而且在写的时候都用锁的方式保证线程安全

ReferenceEntry{K, V> :是可以单性链表

这个是包含key和ValueReference,还有一个重要的就是next,这个指向前一个节点。

eg: 列表中

1 -> null

2 -> 1 -> null

3 ->2 -> 1 ->null

首先获得的节点ReferenceEntry{K, V>是3,3指向2,2 指向1 ….

//这个是存放value的
ValueReference<K, V> getValueReference();
//这个是指向前一个节点  eg :  ,在外面的就是2  ,可以依次寻找每个节点,所以它是线性列表
@Nullable
ReferenceEntry<K, V> getNext();
int getHash();
//key,任意类型
@Nullable
K getKey();
//访问的时间
long getAccessTime();
//写入的时间
long getWriteTime();
...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: