我在多线程应用程序中常用的数据结构是 ConcurrentHashMap,我想在其中保存一组共享相同键的项目。安装特定键值的第一个项目时会出现此问题。
我一直使用的模式是:
final ConcurrentMap<KEYTYPE, Set<VALUETYPE>> hashMap = new ConcurrentHashMap<KEYTYPE, Set<VALUETYPE>>();
// ...
Set<VALUETYPE> newSet = new HashSet<VALUETYPE>();
final Set<VALUETYPE> set = hashMap.putIfAbsent(key, newSet)
if (set != null) {
newSet = set;
}
synchronized (newSet) {
if (!newSet.contains(value)) {
newSet.add(value);
}
}
是否有更好的模式来执行此操作?这甚至是线程安全的吗?有没有更好的类用于内部Set
than java.util.HashSet
?
我强烈建议使用谷歌番石榴 http://code.google.com/p/guava-libraries/为此的库,特别是一个实现Multimap http://docs.guava-libraries.googlecode.com/git-history/v11.0.2/javadoc/com/google/common/collect/Multimap.html. The 哈希多重映射 http://docs.guava-libraries.googlecode.com/git-history/v11.0.2/javadoc/com/google/common/collect/HashMultimap.html将是你最好的选择,但如果你需要并发更新选项,你需要使用将其包装在委托中Multimaps.synchronizedSetMultimap() http://docs.guava-libraries.googlecode.com/git-history/v11.0.2/javadoc/com/google/common/collect/Multimaps.html#synchronizedSetMultimap%28com.google.common.collect.SetMultimap%29.
另一种选择是使用ComputingMap
(也来自 Guava),这是一个映射,如果从调用返回值get(Key)
不存在,它会在此时被实例化。ComputingMap
s 是使用创建的MapMaker http://docs.guava-libraries.googlecode.com/git-history/v11.0.2/javadoc/com/google/common/collect/MapMaker.html.
你的问题的代码大致是:
ConcurrentMap<KEYTYPE, Set<VALUETYPE>> hashMap = new MapMaker()
.makeComputingMap(
new Function<KEYTYPE, VALUETYPE>() {
public Graph apply(KEYTYPE key) {
return new HashSet<VALUETYPE>();
}
});
The Function
仅当调用时才会被调用get()
否则,对于特定键将返回 null。这意味着您可以执行以下操作:
hashMap.get(key).put(value);
安全地知道HashSet<VALUETYPE>
如果尚不存在则创建。
MapMaker
也是相关的,因为它为您提供了对返回的 Map 的调整的控制,让您可以使用该方法指定并发级别等concurrencyLevel()
。您可能会发现这很有用:
指导更新操作之间允许的并发性。用作内部尺寸的提示。该表在内部进行分区,以尝试允许指定数量的并发更新而不会出现争用。由于这些分区的条目分配不一定是统一的,因此观察到的实际并发性可能会有所不同。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)