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. Android 控件属性

    TextView 文字属性//文字左右居中android:layout_centerHorizontal="true"//文字垂直居中android:layout_centerVe ...

  2. 【Xamarin 挖墙脚系列:Windows 10 一个包罗万象的系统平台】

    build2016 结束后,证实了微软之前的各种传言.当然,都是好消息. Windows10 上基本可以运行主流的任意的操作系统. Windows Linux(在内部版本143216中,支持了bash ...

  3. Easyui几种布局方式的使用

    1.通过标记创建layout.  记得添加"easyui-layout"样式给div标记. <div id="cc" class="easyui ...

  4. vmware配置安装JDK、Tomcat以及项目部署

    1.安装JDK1.7 JDK:http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html 安 ...

  5. linux中的strings命令简介2

    摘自:http://blog.csdn.net/stpeace/article/details/46641069 linux中的strings命令简介 之前我们聊过linux strings的用法和用 ...

  6. Android得到一个闹钟在第三方

    收集报警信息 闹铃时间,闹铃备注信息 闹铃引起系统变化的点: 1. Send Notification (正点闹钟能够设置不发送) 2. Play audio 闹铃信息结构体 ClockInfo{ S ...

  7. iOS开发-使用Storyboard进行界面跳转及传值

    前言:苹果官方是推荐我们将所有的UI都使用Storyboard去搭建,Storyboard也是一个很成熟的工具了.使用Storyboard 去搭建所有界面,我们可以很迅捷地搭建出复杂的界面,也就是说能 ...

  8. IOS中的几中观察监听模式

    本文介绍Objective C中实现观察者模式(也被称为广播者/监听者.发布/注册或者通知)的五种方法以及每种方法的价值所在. 该文章将包括: 1 手动广播者和监听者(Broadcaster and ...

  9. sublime text 2 安装

    下载 http://pan.baidu.com/s/1eRemu0y http://jingyan.baidu.com/album/ff4116259b057c12e48237b8.html?pici ...

  10. UVA 10954 Add All

    题意: 给出n个数,要将n个数相加,每次相加所得的值为当次的计算量,完成所有的求和运算后,要求总的计算量最小. 分析: 直接一个优先队列,由小到大排序,每次前两个相加就好. 代码: #include ...