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

Noa*_*oam 0 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);
}
Run Code Online (Sandbox Code Playgroud)

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

man*_*uti 6

该文档ConcurrentHashMap包含有关该行为的一些详细信息.首先我们看一下ConcurrentHashMap.values():

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

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

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

有趣的是术语"弱一致"Spliterator.CONCURRENT,其中前者被描述为:

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

  • 他们可以与其他业务同时进行
  • 他们永远不会扔 ConcurrentModificationException
  • 它们可以保证在构造时只存在一次元素,并且可以(但不保证)反映构造后的任何修改.

Spliterator.CONCURRENT描述为:

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

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