【问题标题】:Guava CacheBuilder doesn't call removal listenerGuava CacheBuilder 不调用删除侦听器
【发布时间】:2014-03-26 01:03:38
【问题描述】:

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

我试过了:设置移除监听器。

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

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

代码:

我的加载缓存:

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 上分享完整的演示,请告诉我

【问题讨论】:

    标签: java collections guava


    【解决方案1】:

    这是因为 Guava 不保证在超时值到期时自动驱逐这些值。但是,它会在一系列读写操作期间执行此操作。

    根据其文档here

    使用 CacheBuilder 构建的缓存不执行清理和逐出值 “自动”或在值过期后立即,或任何 排序。相反,它在期间执行少量维护 写操作,或者在偶尔的读操作期间,如果写是 很少见。

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

    要在到期时验证您的onRemoval,请在您的第二次读取操作之前调用cache#cleanUp,它应该调用您的onRemoval

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    相关资源
    最近更新 更多