在迭代它时从ConcurrentHashMap添加和删除值

时间:2017-01-03 18:08:07

标签: java collections concurrency java-8 java-stream

我有这段代码:

private ConcurrentMap<String, Integer> myMap = new ConcurrentHashMap<>();

 @Scheduled(fixedDelay = 600_000)
 public void foo(){     
    myMap.values().stream().
                filter(predicate()).
                forEach(this::remove);
}

public void insert(String str, Integer value){
   myMap.put(str, value);
}

如果在迭代此地图时会发生什么情况 - 有人会在其中添加新值或从中删除现有值?

1 个答案:

答案 0 :(得分:6)

ConcurrentHashMap的文档包含有关该行为的一些详细信息。首先,我们看看ConcurrentHashMap.values()做了什么:

  

返回此地图中包含的值的Collection视图...

     

视图的迭代器和分裂器弱一致

     

视图的spliterator报告 Spliterator.CONCURRENT Spliterator.NONNULL

有趣的是"weakly consistent"Spliterator.CONCURRENT这两个词,前者被描述为:

  

大多数并发Collection实现(包括大多数队列)也与通常的java.util约定不同,因为它们的迭代器和Spliterators提供弱一致性而不是快速失败遍历:

     
    
        
  • 他们可以与其他行动同时进行
  •     
  • 他们永远不会抛出ConcurrentModificationException
  •     
  • 他们可以保证在施工时只存在一次元素,并且可能(但不保证)反映施工后的任何修改。
  •     
  

Spliterator.CONCURRENT被描述为:

  

特征值,表示可以在没有外部同步的情况下由多个线程安全地同时修改元素源(允许添加,替换和/或删除)。如果是这样,Spliterator应该有关于遍历期间修改影响的文档化政策。

从所有这些文档中,并且与ConcurrentHashMap的并发模型一致,这意味着流管道完全是线程安全的,并且将遍历创建迭代器时存在的元素。 / p>