java 大师,
目前我们有一个 HashMap<String,SomeApplicationObject>
它经常被读取,偶尔会被修改,在修改/重新加载过程中,读取操作会返回一些问题 null
这是不可接受的。
要解决此问题,我有以下选项:
答。使用concurrenthashmap
这看起来像是第一选择,但我们所说的手术是 reload()
-手段 clear()
然后 replaceAll()
. 所以如果 Map
正在阅读文章 clear()
以及 replaceAll()
它返回null,这是不需要的。即使我 synchronize
这并不能解决问题。
b。基于reentrantreadwritelock创建另一个实现
在那里我会创造 Write Lock
之前 reload()
操作。这似乎更合适,但我觉得必须有一些已经可以为这个,我不需要重新发明车轮。
最好的出路是什么?
编辑是否已有具有此功能的集合可用?
3条答案
按热度按时间a0x5cqrl1#
你似乎不确定彼得·劳里的建议是如何实现的。可能是这样的:
不存在并发问题,因为:
新Map是通过局部变量创建的,根据定义,局部变量不是共享的-
getNewValues
不需要同步或原子转让给
map
是原子的map
是可变的,这保证了其他线程将看到更改ldxq2e6h2#
既然你正在重新加载Map,我会在重新加载时替换它。
您可以通过使用volatileMap来实现这一点,当更新它时,您可以完全替换它。
omjgkv6w3#
这听起来很像Guava
Cache
,尽管这实际上取决于如何填充Map,以及如何计算值(披露:我为Guava捐款。)真正的问题是您是否可以指定如何计算
SomeApplicationObject
给定输入String
. 根据你目前告诉我们的,可能是这样的。。。然后,每当你想重建缓存,你只要调用
cache.invalidateAll()
. 用一个LoadingCache
,然后你可以打电话cache.get(key)
如果它还没有计算出这个值,它将被重新计算。或者在打过电话之后cache.invalidateAll()
,您可以拨打cache.loadAll(allKeys)
,但是您仍然需要能够一次加载单个元素,以防在两个元素之间出现任何查询invalidateAll
以及loadAll
.如果这是不可接受的--如果你不能单独加载一个值,你必须一次加载所有的值--那么我将继续使用peter lawrey的方法--保持
volatile
对Map的引用(理想情况下是ImmutableMap
),重新计算整个Map,并在完成后将新Map分配给引用。