[由零开始]Guava Cache原理

GuavaCache核心原理之数据结构

Guava Cache的数据结构跟ConcurrentHashMap类似,但也不完全一样。最基本的区别是
ConcurrentMap会一直保存所有添加的元素,直到显式地移除。
相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。其数据结构图如下:

在这里插入图片描述

  • LocalCache为Guava Cache的核心类,包含一个Segment数组组成

  • Segement数组的长度决定了cache的并发数

  • 每一个Segment使用了单独的锁,其实每个Segment继承了ReentrantLock,对Segment的写操
    作需要先拿到锁

  • 每个Segment由一个table和5个队列组成

  • 5个队列:
    ReferenceQueue keyReferenceQueue : 已经被GC,需要内部清理的键引用队列
    ReferenceQueue valueReferenceQueue : 已经被GC,需要内部清理的值引用队列
    ConcurrentlinkedQueue<ReferenceEntry<k,v>> recencyQueue : LRU队列,当segment上达到
    临界值发生写操作时该队列会移除数据
    Queue<ReferenceEntry<K, V>> writeQueue:写队列,按照写入时间进行排序的元素队列,写入
    一个元素时会把它加入到队列尾部
    Queue<ReferenceEntry<K, V>> accessQueue:访问队列,按照访问时间进行排序的元素队列,
    访问(包括写入)一个元素时会把它加入到队列尾部

  • 1个table:
    AtomicReferenceArray<ReferenceEntry<K, V>> table:AtomicReferenceArray可以用原子方式
    更新其元素的对象引用数组

  • ReferenceEntry<k,v>
    ReferenceEntry是Guava Cache中对一个键值对节点的抽象,每个ReferenceEntry数组项都是一
    条ReferenceEntry链。并且一个ReferenceEntry包含key、hash、valueReference、next字段
    (单链)
    Guava Cache使用ReferenceEntry接口来封装一个键值对,而用ValueReference来封装Value值

guava cache的数据结构的构建流程:

1)构建CacheBuilder实例cacheBuilder

2)cacheBuilder实例指定缓存器LocalCache的初始化参数

3)cacheBuilder实例使用build()方法创建LocalCache实例(简单说成这样,实际上复杂一些)

3.1)首先为各个类变量赋值(通过第二步中cacheBuilder指定的初始化参数以及原本就定义好的一堆常量)

3.2)之后创建Segment数组

3.3)最后初始化每一个Segment[i]

3.3.1)为Segment属性赋值

3.3.2)初始化Segment中的table,即一个ReferenceEntry数组(每一个key-value就是一个ReferenceEntry)

3.3.3)根据之前类变量的赋值情况,创建相应队列,用于LRU缓存回收算法

GuavaCache核心原理之回收机制

Guava Cache提供了三种基本的缓存回收方式:

  • 基于容量回收
    在缓存项的数目达到限定值之前,采用LRU的回收方式
  • 定时回收
    expireAfterAccess:缓存项在给定时间内没有被读/写访问,则回收。回收顺序和基于大小回收一
    样(LRU)
    expireAfterWrite:缓存项在给定时间内没有被写访问(创建或覆盖),则回收
  • 基于引用回收
    通过使用弱引用的键、或弱引用的值、或软引用的值,Guava Cache可以垃圾回收

除了以上三种还有主动删除,采用命令,这个前面讲了
GuavaCache构建的缓存不会"自动"执行清理和回收工作,也不会在某个缓存项过期后马上清理,也没
有诸如此类的清理机制。
GuavaCache是在每次进行缓存操作的时候,惰性删除 如get()或者put()的时候,判断缓存是否过期

GuavaCache核心原理之Segment定位

先通过key做hash定位到所在的Segment
通过位运算找首地址的偏移量 SegmentCount>=并发数且为2的n次方

V get(K key, CacheLoader<? super K, V> loader) throws ExecutionException {
// 注意,key不可为空
int hash = hash(checkNotNull(key));
// 通过hash定位到segment数组的某个Segment元素,然后调用其get方法
return segmentFor(hash).get(key, hash, loader);
}

再找到segment中的Entry链数组,通过key的hash定位到某个Entry节点

V get(K key, int hash, CacheLoader<? super K, V> loader) throws
ExecutionException {
checkNotNull(key);
checkNotNull(loader);
try {
if (count != 0) { // read-volatile
// 内部也是通过找Entry链数组定位到某个Entry节点
ReferenceEntry<K, V> e = getEntry(key, hash);
......
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Guava Cache是Google提供的一套Java工具包中的一部分,它是一套非常完善的本地缓存机制(JVM缓存)。它的设计灵感来源于ConcurrentHashMap,可以按照多种策略来清理存储在其中的缓存值,同时保持很高的并发读写性能。在使用Guava Cache时,可以通过get()或者put()等方法进行缓存操作,当进行这些操作时,Guava Cache会进行惰性删除,即在获取或者放置缓存的时候判断缓存是否过期并进行删除。在Guava Cache的核心原理中,使用Segment来进行缓存值的定位和管理。在创建Guava Cache对象时,可以使用CacheLoader来自动加载数据到缓存中,当缓存不存在时,CacheLoader会负责获取数据并将其放置到缓存中。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [[由开始]Guava Cache介绍和用法](https://blog.csdn.net/qq497811258/article/details/108260969)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Guava Cache简介、应用场景分析、代码实现以及核心的原理](https://blog.csdn.net/weixin_44795847/article/details/123702038)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值