Guava缓存器的删除消息机制
测试代码——          
      LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
                .maximumSize(3)
                .expireAfterWrite(10, TimeUnit.SECONDS)
                .recordStats()
                .removalListener(new RemovalListener<String, Integer>() {
                        @Override
                        public void onRemoval(RemovalNotification<String, Integer> rn) {
                            System.out.println(rn.getKey() + "被移除");
                        }
                })
                .build(
                        new CacheLoader<String, Integer>() {
                                @Override
                                public Integer load(String key) throws Exception {
                                        return  num++; //初始值为1;
                                }
                        });
        try {
                System.out.println(cache.get("a"));
                System.out.println(cache.get("b"));
                System.out.println(cache.get("c"));
                System.out.println(cache.get("d"));
                System.out.println(cache.get("e"));
        } catch (ExecutionException e) {
                e.printStackTrace();
        }
 
      测试结果:
 
 
因为缓存大小为3,依次查询到c时,缓存已满,当查询d时,a将被移除,当查询e时,b将被移除。
 
      
      CacheBuilder的removalListener方法中,将其监听器参数赋值给成员变量removalListener,在LocalCache构造函数中,又传给LocalCache的删除监听器removalListener。至于removalNotificationQueue,也在LocalCache构造函数初始化:new ConcurrentLinkedQueue<RemovalNotification<K, V>>()。
        RemovalNotification为清除单条数据的通知,不管CacheBuilder中设置的键值引用级别是什么,此类保存的是键值的强引用,如果键值已经被垃圾回收器收集,则可能为空。

在引起缓存数据清除的操作中,都会将删除消息放入队列removalNotificationQueue中,入队主体函数: void enqueueNotification(K key, int hash, ValueReference<K, V> valueReference, RemovalCause cause)
参数cause表明引发此次删除操作的原因,为RemovalCause枚举类型,原因有以下几种:
        1)EXPLICIT:键值被用户手动删除,当用户调用invalidate,invalidateAll,remove时, 会发生这种情况 。
        2)REPLACED:键值发生替换。当用户调用put,refresh,putAll, replace时, 会发生这种情况 。
        3)COLLECTED:垃圾回收引起键值被自动清除,在使用weakKeys,weakValues 或 softValues时, 会发生这种情况 。
        4)EXPIRED:键值过期,在使用expireAfterAccess 或 expireAfterWrite时,会发生这种情况。
        5)SIZE:缓存大小限制引起键值被清除,在使用maximumSize 或 maximumWeight时,会发生这种情况。

        在入消息队列时,使用的是Queue的offer方法,如果队列已满,将返回false,而不会报IllegalStateException异常。

对删除消息的处理在下面函数中:      
      void processPendingNotifications() {
            RemovalNotification<K, V> notification;
            while ((notification = removalNotificationQueue.poll()) != null) {
                  try {
                        removalListener.onRemoval(notification);
                  } catch (Throwable e) {
                        logger.log(Level.WARNING, "Exception thrown by removal listener", e);
                  }
            }
      }

该函数被调用的过程如下: 
processPendingNotifications
              ←runUnlockedCleanup
                           ←cleanUp(清零readCount)
                                       ←postReadCleanup(readCount增1) 
                           ←postWriteCleanup
        只要涉及键值的读操作,都将执行postReadCleanup操作,每次执行postReadCleanup操作时readCount都增1,当其达到64时(DRAIN_THRESHOLD为0x3F,即0011 1111),引发cleanUp操作。                  
      if ((readCount.incrementAndGet() & DRAIN_THRESHOLD) == 0) {
            cleanUp();
      }
 而只要涉及键值的写操作,都将执行postWriteCleanup操作。

Guava缓存器源码分析——删除消息的更多相关文章

  1. Guava缓存器源码分析——缓存统计器

    Guava缓存器统计器实现: 全局统计器——         1.CacheBuilder的静态成员变量Supplier<StatsCounter> CACHE_STATS_COUNTER ...

  2. 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  3. Linux 内核调度器源码分析 - 初始化

    导语 上篇系列文 混部之殇-论云原生资源隔离技术之CPU隔离(一) 介绍了云原生混部场景中CPU资源隔离核心技术:内核调度器,本系列文章<Linux内核调度器源码分析>将从源码的角度剖析内 ...

  4. linux调度器源码分析 - 运行(四)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 之前的文章已经将调度器的数据结构.初始化.加入进程都进行了分析,这篇文章将主要说明调度器是如何在程序稳定运 ...

  5. linux调度器源码分析 - 初始化(二)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 上期文章linux调度器源码分析 - 概述(一)已经把调度器相关的数据结构介绍了一遍,本篇着重通过代码说明 ...

  6. 一步步实现windows版ijkplayer系列文章之三——Ijkplayer播放器源码分析之音视频输出——音频篇

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  7. 源码分析 Kafka 消息发送流程(文末附流程图)

    温馨提示:本文基于 Kafka 2.2.1 版本.本文主要是以源码的手段一步一步探究消息发送流程,如果对源码不感兴趣,可以直接跳到文末查看消息发送流程图与消息发送本地缓存存储结构. 从上文 初识 Ka ...

  8. 源码分析Kafka 消息拉取流程

    目录 1.KafkaConsumer poll 详解 2.Fetcher 类详解 本节重点讨论 Kafka 的消息拉起流程. @(本节目录) 1.KafkaConsumer poll 详解 消息拉起主 ...

  9. guava eventbus 原理+源码分析

    前言: guava提供的eventbus可以很方便的处理一对多的事件问题, 最近正好使用到了,做个小结,使用的demo网上已经很多了,不再赘述,本文主要是源码分析+使用注意点+新老版本eventbus ...

随机推荐

  1. 一步一步学python(五) -条件 循环和其他语句

    1.print 使用逗号输出 - 打印多个表达式也是可行的,但要用逗号隔开 >>> print 'chentongxin',23 SyntaxError: invalid synta ...

  2. 如何实现Linux下的U盘(USB Mass Storage)驱动

    如何实现Linux下的U盘(USB Mass Storage)驱动 版本:v0.7 How to Write Linux USB MSC (Mass Storage Class) Driver Cri ...

  3. unity3D 锁屏再开程序崩溃

    在Uniyt3d 调用Android Plugin 的时候,会出现锁屏后再开,程序就崩溃的的现象,解决办法就是在 AndroidManifest.xml 加入  android:configChang ...

  4. C读txt到二维数组

    #include<stdio.h> #include<stdlib.h> #define maxn 200 void main() { FILE *fp; int s[maxn ...

  5. C链表之创建简单静态链表

    C代码: #include<stdio.h> #include<stdlib.h> #include<malloc.h> //创建简单静态链表 typedef st ...

  6. 【FSFA 读书笔记】Ch4 Volume Analysis & Cr 5 PC-based Partitions

    Volume Analysis 1. “卷”可以理解为从逻辑上对物理存储设备的重新编制,便于操作系统管理. (A volume is a collection of addressable secto ...

  7. Sonar入门(二): Maven集成Sonar

    Sonar对maven提供了简单可配的支持,要做的事情很简单——在maven/conf下settings.xml <profiles></profiles>标签之间添加如下内容 ...

  8. Avoid The Lakes

    Avoid The Lakes Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) To ...

  9. ZCTF-Pwn

    版权声明:本文为博主原创文章,未经博主允许不得转载.  最近有了点时间,把ZCTF的pwn总结了下,就差最后一个pwn500,另找时间总结. 文件打包:http://files.cnblogs.com ...

  10. sql linq lambda 对比

    . 查询Student表中的所有记录的Sname.Ssex和Class列. select sname,ssex,class from student Linq: from s in Students ...