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. C# 如何获取当前应用程序的父目录

    //获取当前运行路径的上级目录(父目录) System.IO.DirectoryInfo topDir = System.IO.Directory.GetParent(System.Environme ...

  2. 注册flash.ocx inno setup (转)

    ; 脚本由 Inno Setup 脚本向导 生成! ; 有关创建 Inno Setup 脚本文件的详细资料请查阅帮助文档! #define MyAppName "xx模块" #de ...

  3. linux之SQL语句简明教程---AND OR

    在上一页中,我们看到 WHERE 指令可以被用来由表格中有条件地选取资料. 这个条件可能是简单的 (像上一页的例子),也可能是复杂的.复杂条件是由二或多个简单条件透过 AND 或是 OR的连接而成.一 ...

  4. CGFW时装发布及活动整体一览表

    CGFW时装发布及活动整体一览表 CGFW时装发布及活动整体一览表

  5. 关于xxx.h file not found 的问题

    在引用第三方库的时候,经常会遇到xxx.h file not found的问题. 首先,我们要知道在引用第三方的时候,我们使用的第三方的库的类型. .a静态库 使用方式:#import "x ...

  6. Zipper

      Zipper Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  7. ASP.NET 委托,异步调用例子 .

    简要介绍:1.定义异步执行需要调用的方法2.定义具有与异步执行方法相同签名的委托(Delegate):3.调用 BeginInvoke 和 EndInvoke 方法.   3.1. BeginInvo ...

  8. K-近邻算法python实现

    内容主要来源于机器学习实战这本书.加上自己的理解. 1.KNN算法的简单描写叙述 K近期邻(k-Nearest Neighbor.KNN)分类算法能够说是最简单的机器学习算法了. 它採用測量不同特征值 ...

  9. Android通过HTTP POST带參訪问asp.net网页

    在看了网络上非常多视频关于android通过HTTP POST或者GET方式訪问网页并获取数据的方法. 自己也copy了一份来測试.并通过C#.NET搭建了一个简单的后台,但发现传參时,依照网上的方式 ...

  10. 实用的JavaScript技巧、窍门和最佳实践

    JavaScript是世界上第一的编程语言,它是Web的语言,是移动混合应用(mobile hybrid apps)的语言(比如 PhoneGap或者 Appcelerator),是服务器端的语言(比 ...