番石榴缓存:取消对特定缓存值的驱逐

时间:2013-07-23 14:41:42

标签: java caching guava

Heyho,

目前正在使用guava缓存用户。所以我的问题是,如果缓存的对象具有特定的属性值,是否可以使用guava来重新删除条目的驱逐。例如,如果user.isOnline()返回true,则即使未在特定时间内访问用户,也不会逐出用户(.expireAfterAccess(KEEP_LOADED,TimeUnit.SECONDS))。

修改

我在CacheBuilder.weighter(...)的javadoc中找到了这个:

  

当条目的权重为零时,不会考虑基于大小的驱逐(尽管它仍可能通过其他方式驱逐)。

但如果他在线,我不想以任何方式驱逐我的用户。

基本上我用这种方式缓存用户:

        this.cache = CacheBuilder.newBuilder()
            .maximumSize(MAX_CACHED_USERS)
            .expireAfterAccess(KEEP_LOADED, TimeUnit.SECONDS)
            .build(new UserLoader(core));

修改

好吧,我可以用weighter来限制我的缓存大小。对于每个在线用户,我可以返回0和其他每个用户1.这将导致缓存保持在线用户。但是如果使用maximumSize和expireAfterAccess会很好。但CacheBuilder.weighter(...)不会阻止expireAfterAccess(...)设置以驱逐旧用户。

修改

也许有可能以某种方式取消驱逐,但我不确定如何:/

与:Is it safe to reinsert the entry from Guava RemovalListener?

相关

最高

1 个答案:

答案 0 :(得分:0)

您链接的问题直接描述了如何处理此模式。

  

我使用一张地图和一个缓存。将地图用于仍在进行中的作业,并可能使用缓存的RemovealListener从地图中删除条目?

简单地说,如果有数据你不想被驱逐,它就不属于驱逐的数据结构。

对于您的用例,您需要维护已登录用户的地图和最近登录用户的缓存。当用户登录时,他们将存储在标准地图中。当他们注销时,他们的对象被移动到缓存中,这最终将逐出它们。

您可以(并且应该)在包含地图和缓存的对象中隐藏此行为。这可能类似于:

public class UserStore {
  private final ConcurrentHashMap<Key, User> loggedIn;
  private final LoadingCache<Key, User> recentlyAccessed;

  ...

  public User getUser(Key userKey) {
    User user = loggedIn.get(userKey);
    if (user != null) {
      return user;
    }
    return recentlyAccessed.getUnchecked(userKey); // or .get() if necessary
  }
}