ConcurrentLinkedHashMap.Builder 如何处理删除和获取?
How does ConcurrentLinkedHashMap.Builder handles deletions and get?
我将 ConcurrentLinkedHashMap 用作 LRUCache
我很好奇它如何处理 deletion
后的 .get
键(因为我们最终必须删除键由于其政策,来自 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;
}
}
我该如何处理这种情况 ConcurrentLinkedHashMap
class?
谢谢
在这种情况下,您可能希望避免从缓存中多次读取以避免竞争条件。相反,你会写成,
Entity getEntity(GUID entityId) {
Entity entity = entityLRUCache.get(entityId);
if (entity == null) {
entity = longLoadFromDatabase(entityId);
entityLRUCache.put(entityId, entity);
}
return entity;
}
当加载未命中的值以填充时,这有一个称为缓存踩踏的竞争。对于该库,如果有问题,可以使用锁条带化或存储期货来编写装饰器来避免这种情况。 Google 代码 wiki 用于提供如何编写 SelfPopulatingMap.
的示例
ConcurrentLinkedHashMap
合并成Guava,进化成Caffeine。你应该更喜欢那个库,你可以把它写成,
Entity getEntity(GUID entityId) {
return entityCache.get(entityId, this::longLoadFromDatabase);
}
我将 ConcurrentLinkedHashMap 用作 LRUCache
我很好奇它如何处理 deletion
后的 .get
键(因为我们最终必须删除键由于其政策,来自 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;
}
}
我该如何处理这种情况 ConcurrentLinkedHashMap
class?
谢谢
在这种情况下,您可能希望避免从缓存中多次读取以避免竞争条件。相反,你会写成,
Entity getEntity(GUID entityId) {
Entity entity = entityLRUCache.get(entityId);
if (entity == null) {
entity = longLoadFromDatabase(entityId);
entityLRUCache.put(entityId, entity);
}
return entity;
}
当加载未命中的值以填充时,这有一个称为缓存踩踏的竞争。对于该库,如果有问题,可以使用锁条带化或存储期货来编写装饰器来避免这种情况。 Google 代码 wiki 用于提供如何编写 SelfPopulatingMap.
的示例ConcurrentLinkedHashMap
合并成Guava,进化成Caffeine。你应该更喜欢那个库,你可以把它写成,
Entity getEntity(GUID entityId) {
return entityCache.get(entityId, this::longLoadFromDatabase);
}