Java ConcurrentLinkedHashMap.Builder如何处理删除和获取?
我使用as LRUCache,我很好奇它是如何处理的。删除密钥后获取,因为由于其策略,我们最终将不得不从LRUCache中删除密钥Java ConcurrentLinkedHashMap.Builder如何处理删除和获取?,java,data-structures,concurrency,concurrenthashmap,Java,Data Structures,Concurrency,Concurrenthashmap,我使用as LRUCache,我很好奇它是如何处理的。删除密钥后获取,因为由于其策略,我们最终将不得不从LRUCache中删除密钥 entityLRUCache = new ConcurrentLinkedHashMap.Builder<GUID, Entity>() .maximumWeightedCapacity(100)
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类处理这些类型的情况
多亏了在这种情况下,您可能希望避免从缓存中多次读取以避免竞争条件。相反,你会这样写
Entity getEntity(GUID entityId) {
Entity entity = entityLRUCache.get(entityId);
if (entity == null) {
entity = longLoadFromDatabase(entityId);
entityLRUCache.put(entityId, entity);
}
return entity;
}
Entity getEntity(GUID entityId) {
return entityCache.get(entityId, this::longLoadFromDatabase);
}
当加载值以填充未命中时,这有一个称为缓存踩踏的竞争。对于该库,可以编写一个使用锁条带化或存储未来的装饰器,以避免出现问题。谷歌代码维基(GoogleCodeWiki)提供了一个如何编写代码的示例
ConcurrentLinkedHashMap合并到番石榴中,并演变为。你应该更喜欢那个图书馆,在那里你可以把它写成
Entity getEntity(GUID entityId) {
Entity entity = entityLRUCache.get(entityId);
if (entity == null) {
entity = longLoadFromDatabase(entityId);
entityLRUCache.put(entityId, entity);
}
return entity;
}
Entity getEntity(GUID entityId) {
return entityCache.get(entityId, this::longLoadFromDatabase);
}
后一个选项也会有缓存踩踏吗?不,它会为您处理无锁读取,然后是每项锁以计算它。如果longLoadFromDatabase是异步的,即从RxJava返回单值,我如何能够很好地调整后一个选项?我确实找到了RxJava后面的write,但我仍然不太清楚。@AlexKokorin您考虑过AsyncLoadingCache吗?