Guava CacheBuilder不会调用remove listener

时间:2014-02-24 11:33:35

标签: java collections guava

我想: 在实体因超时到期而被删除时收到通知。

我尝试过: 设置删除侦听器。

问题: 似乎删除侦听器无法正常工作。它仅在我将新项目放入缓存时才起作用(参见下面的代码)

问题: 如何在不放置新项目的情况下使删除侦听器工作?

代码:

我的加载缓存:

LoadingCache<String, Integer> ints = CacheBuilder.newBuilder()
            .maximumSize(10000)
            .expireAfterAccess(ACCESS_TIMEOUT, TimeUnit.MILLISECONDS)
            .removalListener(
                    new RemovalListener() {
                        //PROBLEM: THIS METHOD IS NEVER CALLED!!!
                        public void onRemoval(RemovalNotification notification) {
                            if (notification.getCause() == RemovalCause.EXPIRED) {
                                System.out.println("Value " + notification.getValue() + " has been expired");
                            } else {
                                System.out.println("Just removed for some reason");
                            }
                        }
                    }
            )
            .build(
                    new CacheLoader<String, Integer>() {
                        public Integer load(String key) throws Exception {
                            return new Integer(-1);
                        }
                    });

我如何在单独的线程中使用缓存:

cache.put("key", 100);
Thread.sleep(ACCESS_TIMEOUT / 2);
System.out.println(cache.getIfPresent(key)); //returns 100
Thread.sleep(ACCESS_TIMEOUT * 5);
//CRUCIAL STRING: cache.put("key2", 200); //invoke removal listener
System.out.println(cache.getIfPresent(key)); //return null
//And again: the problem is that entity has been already expired, but removal listener isn't called untill I add new item to the cache.

P.S: 如果需要,我可以在GitHub分享完整的演示,只需告诉我

1 个答案:

答案 0 :(得分:13)

这是因为当超时值到期时,Guava无法确保自动驱逐值。但是,它会在一系列读写操作中执行此操作。

根据其文档here

  

使用CacheBuilder构建的缓存不执行清理并逐出值   “自动”,或在值到期后立即或任何其他内容   那种。相反,它在执行期间执行少量维护   写入操作,或者在写入时偶尔进行读取操作   罕见的。

     

原因如下:如果我们想执行Cache   维护不断,我们需要创建一个线程,它的   操作将与共享锁的用户操作竞争。   此外,某些环境限制线程的创建,   这将使CacheBuilder在该环境中无法使用。

要在onRemoval到期时验证,请在第二次阅读操作之前立即致电cache#cleanUp,并且应该拨打onRemoval