带有过期的不可变集合

时间:2014-07-11 15:47:44

标签: java guava

我在做什么:我正在收集一个可能很大的对象集合,并要求用户根据集合进行输入。我想缓存对象以避免重新获取它们,但我希望收集在短时间后过期以防用户散失。如果需要,我会重新获取对象。该集合不会在短时间内发生变化。

我看过的内容Guava's Cache因为基于时间的过期而看起来很有希望。然而,有几件事让我感到困扰。我真的不需要地图 - 集合将被完整访问或根本不访问。而且我担心我会遇到竞争条件,当我访问缓存时,缓存中的项目开始到期。这增加了一定程度的复杂性,必须跟踪我的所有项目是否都在缓存中,从而消除了缓存的一些价值。

我的问题:如果我不是将单个项目放入缓存中,而是将其中的单个项目放入缓存中并将其放入缓存中,我是否会遇到麻烦?这似乎是我一次访问整个集合的方式,并且集合在缓存中或者不在(在这种情况下我重建它)。我没有看到这种方法的缺陷吗?

3 个答案:

答案 0 :(得分:5)

为Guava缓存提供静态单例密钥并不罕见。 Cache即使不用作Map,也会带来很多好处。我会做这样的事情:

 private static final Object CACHE_KEY = new Object();

 private LoadingCache<Object, List<SomeType>> cache = 
      CacheBuilder.newBuilder()
        .expireAfterWrite(5, TimeUnit.MINUTES)
        .softValues()
        .build(valuesLoader());

 //...
 List<SomeType> values = cache.get(CACHE_KEY);

在我的代码库中,我在几个地方使用具有单个值的缓存,因此我将其抽象为SingleValueLoadingCache<T>,它公开了一个无参数get()方法并封装了缓存和关键。

  

这似乎是我一次访问整个集合的方式,并且集合在缓存中或者它不是(在这种情况下我重建它)。这种方法是否存在陷阱,我没有看到?

万一您尚未找到它,您可能希望LoadingCache传递CacheLoader build CacheBuilder方法。这样您就可以随时拨打get(),如果该值不在缓存中,则会使用您提供的CacheLoader自动同步加载。

答案 1 :(得分:1)

作为使用单个人工密钥的LoadingCache的替代方法,您可以使用Suppliers.memoizeWithExpiration,这会为您提供稍微简单的API。缺点是它没有公开Cache所做的旋钮和统计数据。

private Supplier<Collection<Foo>> cachingSupplier = 
    Suppliers.memoizeWithExpiration(valueSupplier,
        5L, TimeUnit.MINUTES);

答案 2 :(得分:0)

您的用例似乎将值描述为对象集合。因此,您描述的工作流程“制作一个Guava ImmutableCollection并将其放入缓存中”。是一个适当的行动。

相关问题