首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Guava缓存器源码分析——剔除消息

2013-10-08 
Guava缓存器源码分析——删除消息Guava缓存器的删除消息机制测试代码——LoadingCacheString, Integer cache

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();        }
       测试结果: Guava缓存器源码分析——剔除消息 因为缓存大小为3,依次查询到c时,缓存已满,当查询d时,a将被移除,当查询e时,b将被移除。       Guava缓存器源码分析——剔除消息      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操作。

热点排行