zoukankan      html  css  js  c++  java
  • Guava缓存器源码分析——删除消息

    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操作。
  • 相关阅读:
    mybatis动态查询,模糊查询
    Python 列表
    异步加载实现点赞功能($.load 出现post不支持)
    shiro多账号登录(用户名,手机号,邮箱)
    spring data jpa 级联操作的时候注意事项
    semantic UI 点击按钮自动提交表单原因
    上线日期
    有关弱类型意识、DOM、动态语言与函数式编程
    视频项目时长的存储和程序设计方案---单例模式节省内存空间以及自定义注解
    项目中整合第三方插件与SpringMVC数据格式化关于ip地址
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3331201.html
Copyright © 2011-2022 走看看