【问题标题】:Guava cache return an empty result on the second hitGuava 缓存在第二次命中时返回空结果
【发布时间】:2012-04-24 13:23:29
【问题描述】:

我对番石榴缓存有一个奇怪的(至少对我来说)行为。第一次命中后,以下访问将返回一个空对象。我没有使用奇怪的驱逐,所以我不知道我在哪里做错了。 我声明了以下LoadingCache:

LoadingCache<String, Vector<Location>> locations = CacheBuilder.newBuilder()
            .maximumSize(100000)
            .build(
                    new CacheLoader<String,Vector<Location>>() {
                        @Override
                        public Vector<Location> load(String key)  {
                            return _getLocationListByTranscriptId(key);
                        }
                    });

我只在这个方法中使用过:

public Vector<Location> getLocationListByTranscriptId (String transcriptid) {
    if (transcriptid.equals("TCONS_00000046"))  System.out.println("tcons found, will this work?");
    Vector<Location> result;
    try {
        result = locations.get(transcriptid);
    } catch (ExecutionException e) {
        System.err.println("Error accessing cache, doing the hard way");
        result = _getLocationListByTranscriptId(transcriptid);
    }
    if (transcriptid.equals("TCONS_00000046")){
        if (result.size()==0){
            System.out.println("this is a problem");
            return null;
        }
        System.out.println("this is good!");
    }
    return result;
}

迭代输入字符串的集合,我得到以下输出:

tcons found, will this work?
this is good!
tcons found, will this work?
this is a problem

所以,我第一次使用缓存时,它可以工作,但是 A) 该值未正确存储以供将来访问; B)该值被重置为一些奇怪的行为。 我能做些什么?感谢大家阅读本文!

编辑: 感谢 axtavt 的回答,我可以立即弄清楚我在哪里编辑结果列表。不知道为什么,我确信番石榴缓存会返回值的副本。感谢您的回答,以及有关防御性编程的建议。 (对不起,如果我还不能评价你的答案)。

【问题讨论】:

    标签: java caching guava


    【解决方案1】:

    我相信您无意中清除了代码中某处的Vector。有两种可能:

    • Vector 被从缓存中获取它的代码修改。

      可以通过制作防御性副本(尽管它破坏了缓存的想法)或返回不可变的集合视图来防止此类错误:

      LoadingCache<String, List<Location>> locations = CacheBuilder.newBuilder()
           .maximumSize(100000)
           .build(
                   new CacheLoader<String, List<Location>>() {
                       @Override
                       public List<Location> load(String key)  {
                           return Collections.unmodifiableList(
                               _getLocationListByTranscriptId(key));
                       }
                   }); 
      

      这样修改代码后,很容易发现非法修改集合的地方。

      请注意,Vector 没有不可修改的视图,因此应使用 List

    • _getLocationListByTranscriptId() 将其结果存储在一个字段中,其他方法(或同一方法的其他调用)可以访问该字段。因此,您应该检查 _getLocationListByTranscriptId() 是否没有在字段中留下对其结果的任何引用。

    【讨论】:

    • 一个简单的初学者错误,我相信这也是我的情况:P 感谢您的回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多