Java古鲁,
目前我们有一个HashMap
要解决此问题,我有以下选项:
A.使用并发哈希图
这看起来像是第一个选择,但我们正在谈论的操作是重新加载()
-意味着lear()
后跟replace eAll()
。因此,如果在lear()
和prereplace eAll()
之后读取Map
,它会返回null,这是不可取的。即使我同步
这并不能解决问题。
B.基于ReentantReadWriteLock创建另一个实现
在那里我将在重新加载()
操作之前创建获取写锁
。这似乎更合适,但我觉得必须有一些可用的东西,我不需要重新发明轮子。
最好的出路是什么?
编辑是否已经有任何具有此类功能的收藏?
由于您正在重新加载地图,我会在重新加载时替换它。
您可以通过使用易失性映射来做到这一点,您可以在更新时将其完全替换。
你似乎不确定彼得·劳里的建议如何实施。它可能是这样的:
class YourClass {
private volatile Map<String, SomeApplicationObject> map;
//constructors etc.
public void reload() {
Map<String,SomeApplicationObject> newMap = getNewValues();
map = Collections.unmodifiableMap(newMap);
}
}
没有并发问题,因为:
getNewValue
不需要同步或原子map
的赋值是原子的map
是易失性的,这保证了其他线程会看到变化
这听起来很像Guava的Cache
,尽管它实际上取决于您如何填充地图以及如何计算值。(披露:我为Guava做出了贡献。)
真正的问题是,您是否可以在给定输入String
的情况下指定如何计算您的有应用对象
。根据您到目前为止告诉我们的内容,它可能看起来像这样……
LoadingCache<String, SomeApplicationObject> cache = CacheBuilder.newBuilder()
.build(
new CacheLoader<String, SomeApplicationObject>() {
public SomeApplicationObject load(String key) throws AnyException {
return computeSomeApplicationObject(key);
}
});
然后,每当您想重建缓存时,您只需调用cache. validateAll()
。使用LoadingCache
,您可以调用cache.get(key)
,如果它还没有计算值,它将重新计算。或者在调用cache.validateAll()
之后,您可以调用cache.loadAll(allKeys)
,尽管您仍然需要能够一次加载单个元素,以防validateAll
和loadAll
之间出现任何查询。
如果这是不可接受的——如果您不能单独加载一个值,您必须一次加载所有值——那么我将继续使用Peter Lawrey的方法——保留对映射的易失性
引用(理想情况下是ImmutableMap
),重新计算整个映射,并在完成后将新映射分配给引用。