guava cache 存储的数据结构 --- 2
2016-01-27 17:36
676 查看
注: maxWeight 是缓存数超出设置的数量时就回收最近没有使用的活使用次数少的.
segment数组的初始化 : (先分为几个小段,get(key)时,根据key的hash定位到他是哪一个段内,提高查询效率)
先计算出分配hash段的个数(segment数组的个数)
计算每个segment初始化缓存的数量
为每个segment分配出合适的最大缓存数
根据数组的个数创建segment
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 ….
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(); ...
相关文章推荐
- POJ1363 Rails(数据结构栈)
- 数据结构和算法是程序的根本——为什么?!
- 数据结构(寒假小结)——2.3线性表之双链表和循环链表
- 跟我学数据结构之线性表
- 【Redis笔记(五)】 Redis数据结构 - set集合
- 数据结构--二叉树
- 链表的理解与实现[数据结构]
- python 数据结构
- 数据结构实现之有序符号表BST二叉查找树
- 数据结构(寒假小结)——2.2线性表之单链表
- python数据结构
- 小蚂蚁学习数据结构(25)——图的基本概念和术语
- 数据结构---队列的实现
- 数据结构---无重复元素链表的实现
- 数据结构--栈的实现
- Nginx源码分析 - 基础数据结构篇 - 内存池 ngx_palloc.c
- 二叉排序树的实现
- 集合框架之常用Map实现类对比
- java数据结构详解
- 线段树系列(数据结构)