番石榴缓存:通过删除策略进行手动管理

时间:2014-03-03 18:48:32

标签: java garbage-collection guava

我有这样的事情:

private final Cache<Long, BlockingDeque<Peer>> peers = CacheBuilder.newBuilder()
    .expireAfterAccess(10, TimeUnit.MINUTES)
    .build();

public class Peer {       
    public void hanleRequest(String request) { ... }
    //....
}

Cache仅提供两项政策:expiredAfterWriteexpireAfterAccess。第一个和第二个都适合我。

我希望 BlockingDeque<Peer>实体在最后一次调用属于该Peer#handleRequest()的{​​{1}}对象之一的Peer方法后的10分钟内到期。方法BlockingDeque重置到期计数器。

我想要 Peer#handleRequest()对象的任何其他方法都不会重置计数器。

我想要 peers.get(key)也不会重置计数器。

示例

Peer

问题

  1. 在Guava peers.getIfPresent(key); // doesn't reset counter peers.getIfPresent(key).add(new Peer()); // doesn't reset counter peers.getIfPresent(key).remove(peer); //doesn't reset counter peers.getIfPresent(key).handleRequest(request); // RESET counter! CacheExpiringMap或任何其他番石榴地图的帮助下,这可能吗?
  2. 如果第一个问题的答案是否定的。 我可以自定义其中一个Guava元素,无需从头开始实现所有内容吗?
  3. 如果对第二个问题的回答是否定的。 我自己实现它的更好方法是什么?目前我认为除了守护程序线程之外它还会MapMaker。该线程将每5-15秒遍历整个映射并检查是否有任何实体过期
  4. 更新: 这是一个很好的解决方案吗?我认为,ConcurrentHashMap是一个将对每个用户请求执行的操作,因此它的性能保持在第一位。 handleRequest缓存中的近似BlockingDeque个对象接近10,一个双端队列中的peers对象的近似数量为2。

    Peer

2 个答案:

答案 0 :(得分:3)

首先说一句:你问的问题有点像XY问题,请参阅: https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem 所以也许一些你真正想要实现的背景会很好。

从字面上理解问题,我会做以下事情:

对“不重置计数器”访问使用第二个缓存而不过期。将删除侦听器添加到对等缓存,以从第二个缓存中删除该值。也许只是一个HashMap也没关系。资源使用情况实际上由对等缓存控制。

答案 1 :(得分:1)

@ cruftex建议使用第二个缓存很好。

关于您更新的问题,您无需在“更新”值之前使其无效,只需更新它:

public class Peer {        
    public void handleRequest(String request) { 
        BlockingDeque<Peer> deque = peers.getIfPresent(key);
        if (deque != null) {
            peers.put(key, deque);
        }
        //...
    }
    //....
}