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);
}