我使用ConcurrentLinkedHashMap作为LRUCache
,我很好奇它如何在.get
密钥之后处理deletion
(因为我们最终必须从{删除密钥} {1}}由于其政策。
LRUCache
如何使用此entityLRUCache = new ConcurrentLinkedHashMap.Builder<GUID, Entity>()
.maximumWeightedCapacity(100)
.build();
...
Entity getEntity(GUID entityId)
{
if (entityLRUCache.containsKey(entityId))
{
// Question: what if key gets deleted from other
// thread (when we jumped into this if statement)
// and then we'll try to retrieve it here using .get()
return entityLRUCache.get(entityId);
}
else
{
Entity entity = longLoadFromDatabase(entityId);
entityLRUCache.put(entityId, entity);
return entity;
}
}
类处理这些类型的情况?
由于
答案 0 :(得分:1)
在这种情况下,您可能希望避免从缓存中多次读取以避免竞争条件。相反,你会把它写成,
Entity getEntity(GUID entityId) {
Entity entity = entityLRUCache.get(entityId);
if (entity == null) {
entity = longLoadFromDatabase(entityId);
entityLRUCache.put(entityId, entity);
}
return entity;
}
当加载值以填充未命中时,这会有一个称为缓存标记的竞赛。对于该库,可以使用锁定条带或存储期货来编写装饰器,以避免出现问题。 Google Code维基用于提供如何编写SelfPopulatingMap的示例。
ConcurrentLinkedHashMap
合并为番石榴并演变为Caffeine。你应该更喜欢这个库,你可以把它写成,
Entity getEntity(GUID entityId) {
return entityCache.get(entityId, this::longLoadFromDatabase);
}