Pattern for Java ConcurrentHashMap of Sets



我在多线程应用程序中常用的数据结构是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);
  }
}

是否有更好的模式来执行此操作?这甚至是线程安全的吗?有没有比java.util.HashSet更好的类用于内部Set

我强烈建议为此使用Google Guava库,特别是Multimap的实现。HashMultimap将是你最好的选择,但如果你需要并发更新选项,你需要使用Multimaps.syncdSetMultimap((将其包装在一个委托中。

另一种选择是使用ComputingMap(也来自 Guava(,这是一个映射,如果调用 get(Key) 返回的值不存在,它就会在那里实例化。 ComputingMap是使用地图制作器创建的。

您问题中的代码大致为:

ConcurrentMap<KEYTYPE, Set<VALUETYPE>> hashMap = new MapMaker()
                 .makeComputingMap(
        new Function<KEYTYPE, VALUETYPE>() {
         public Graph apply(KEYTYPE key) {
           return new HashSet<VALUETYPE>();
         }
       });

仅当对特定键的get()调用将返回 null 时,才会调用 Function。这意味着您可以执行以下操作:

hashMap.get(key).put(value);

安全地知道HashSet<VALUETYPE>已创建(如果尚不存在(。

MapMaker 也是相关的,因为它为您提供了对返回 Map 调整的控制,例如,允许您使用方法 concurrencyLevel() 指定并发级别。您可能会发现这很有用:

指导更新操作之间允许的并发性。用作内部大小调整的提示。该表在内部分区,以尝试允许指示数量的并发更新而不会争用。由于向这些分区分配的条目不一定是统一的,因此观察到的实际并发性可能会有所不同。

我认为使用java.util.concurrent.ConcurrentSkipListMapjava.util.concurrent.ConcurrentSkipListSet可以帮助您解决并发问题。

相关内容

  • 没有找到相关文章

最新更新