3

嘿嘿,

目前使用 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));

编辑:

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

编辑:

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

相关:从 Guava RemovalListener 重新插入条目是否安全?

最大限度

4

1 回答 1

1

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

我会使用一张地图和一张缓存。将地图用于仍在进行中的作业,或者使用缓存的 RemovalListener 从地图中删除条目?

简而言之,如果有你不想被驱逐的数据,它就不属于驱逐数据结构。

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

您可以(并且应该)将此行为隐藏在包含地图和缓存的对象中。这可能看起来像:

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
  }
}
于 2016-08-01T04:09:20.940 回答