我正在使用google guava中的ConcurrentHashMap
(通过MapMaker),但该实现并未订购。
google guava中有ConcurrentSkipListMap
,但该结构无法过期。
是否有任何结构可以兼顾两者?
答案 0 :(得分:2)
我会使用ConcurrentSkipListMap
并定期迭代地图以清除过期的内容。因为跳过列表是无限制的,所以当驱逐线程无法赶上时,这开启了内存泄漏的可能性,但实际上这似乎非常非常不可能,除非你做了一些极端的事情。当我没有做到这一点时,我也做了类似的事情。想要使用后台线程:
static AtomicInteger cnt = new AtomicInteger();
Val put(K key, V val){
//Do the usual stuff
if(cnt.getAndIncrement() % 100 == 0){
//iterate map and evict stuff
}
}
if(cnt.getAndIncrement() % 100 == 0)
可能是一个“聪明的优化”,所以也许你可以像matt b暗示的那样每次迭代和逐出。
哦,当你这样做时只需要注意一点......当时间戳重合时,一定要打破不同实体之间的平等:
class Entity implaments Comparable<Entity>{
static AtomicInteger SEQ = new AtomicInteger();
int id = SEQ.getAndIncrement();
long timeStamp = System.currentTimeMillis();
int compareTo(Entity other){
// compare by timestamp
// If timestamps are equal, don't just return 0 yet!!
// Compare by id and return 0 ONLY IF the id equals.
// Otherwise entities disappear from your ordered map and
// it's really annoying to debug.
}
答案 1 :(得分:1)
扩展java.util.LinkedHashMap并覆盖removeEldestEntry()以执行您想要的任何操作。
答案 2 :(得分:0)
听起来你有非常具体和不寻常的要求。你可能不得不自己写。
答案 3 :(得分:0)
如果您有一个有序的地图(我假设订购时间基于时间戳),那么每当您从地图添加或获取项目时,您只需从地图中的最小有序值扫描到当前时间戳 - 60秒并删除任何不足之处。 Map的ordered属性意味着您无需在每次操作时扫描完整列表。
答案 4 :(得分:0)
为什么不使用两张有序地图?一个由时间戳键入,用于查找过期事件。另一个由UUID键入,用于查找事件。删除过期事件时,请使用事件的UUID从第二个地图中删除。
答案 5 :(得分:0)
听起来您想要并发到期地图的有序视图。您可以从ForwardingMap
答案 6 :(得分:0)
良好的到期地图实施很难得到。除了番石榴,您可以查看ExpiringMap。交换已排序的地图实现以满足您的需求应该相当简单。