ConcurrentLinkedHashMap设计与代码解析
ConcurrentLinkedHashMap是google 开源的线程安全的方便并发的Map, Map利用LRU缓存机制(Least recent use 最近最少使用)对Map中存储对象进行换入换出管理,对项目中要求LRU缓存的可以利用.本文是在参阅原开源项目设计文档以及代码阅读的基础上的一个总结,由于能力有限,总结可能存在误差,读者在该开源项目主页下载源代码,阅读设计文档,以更深入熟悉ConcurrentLinkedHashMap的设计
1.总体设计
-
1.1 ConcurrentLinkedHashMap 的主要设计思路
- (1).为提高命中率,采用LRU策略进行存储对象的换入与换出,通过Weigher计算每一个Entry占用的存储单元数(对于分布均匀的,一般一个entry的weightedValue 为1),当存储单元超过预设的Capacity时,需要按照LRU策略换出最近最少使用的Entry, 以LinkedDeque(双向链表实现的队列数据结构) evictionDeque实现LRU策略,每次读写,将Entry移至队尾,换出时从队首依次换出。
- (2).为提高并发,减少进程在争取Map资源时产生的时间消耗, 采用两套资源控制机制,一套同步机制,使用ConcurrentMap对对象数据进行KV存储,保证多线程并发安全地调用Map资源,而对于存储对象的换入换出管理则采用异步机制,使用Queue buffer存储每次的因对象读写而产生的对象换入换出任务(为更好地并发,设置多个buffer, 线程根据线程号映射到不同buffer),当遇到读任务超过阈值或写任务或者时,加锁后,执行buffer中的多个任务,依次对evictionDeque进行节点调整,需要移除的数据,从map中移除。
2.代码解析
-
2.1相关类。
- (1) Weigher 是一个计算每条记录占用存储单元数接口,项目在类Weighers中给了许多针对不同需求的计算方式,如Byte 数组可以通过数组长度计算为存储单元个数,而就一般应用的存储对象,可以直接用SingletonWeigher,每条记录占用一个存储单元。
@ThreadSafe
public interface Weigher<V> {
/**
* Measures an object's weight to determine how many units of capacity that
* the value consumes. A value must consume a minimum of one unit.
*
* @param value the object to weigh
* @return the object's weight
*/
int weightOf(V value);
}
-
: (2)**WeightedValue**是对Value的装饰,包含了Value占用的存储单元个数weight值,以及根据weight值计算状态(pos->active, kept in map and queue; 0->retire,deleted from map but not from queue; neg->dead, deleted from map and queue)
- (3) Node 实现了链接表中Linked Node,便于LinkedDeque的双向索引,是Map以及evictionDeque存储对象。
-
(4)Task 是针对存储对象LRU顺序操作的抽象类,继承自Task的有ReadTask, AddTask, UpdateTask,RemoveTask, 每一个Task有一个根据创建顺序分配的order.
/**

本文详细解析了ConcurrentLinkedHashMap的设计和代码,它是一种线程安全的并发Map,实现了LRU缓存策略。文章涵盖了总体设计、主要操作过程如get、put、remove以及LRU管理的细节,强调了其在读写效率上的优势。

576

被折叠的 条评论
为什么被折叠?



