ConcurrentLinkedHashMap.Builder如何处理删除并获取?

时间:2018-04-28 16:36:44

标签: java data-structures concurrency concurrenthashmap

我使用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; } } 类处理这些类型的情况?

由于

1 个答案:

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