Reputation: 3145
I have this code:
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);
}
What would happen if while iterating over this map - someone will put a new value in it or remove an existing value from it?
Upvotes: 0
Views: 6873
Reputation: 72874
The documentation for ConcurrentHashMap
has some details about the behavior. First we look at what ConcurrentHashMap.values()
does:
Returns a
Collection
view of the values contained in this map...The view's iterators and spliterators are weakly consistent.
The view's
spliterator
reportsSpliterator.CONCURRENT
andSpliterator.NONNULL
.
What's interesting are the terms "weakly consistent" and Spliterator.CONCURRENT
, where the former is described as:
Most concurrent Collection implementations (including most Queues) also differ from the usual
java.util
conventions in that their Iterators and Spliterators provide weakly consistent rather than fast-fail traversal:
- they may proceed concurrently with other operations
- they will never throw
ConcurrentModificationException
- they are guaranteed to traverse elements as they existed upon construction exactly once, and may (but are not guaranteed to) reflect any modifications subsequent to construction.
and Spliterator.CONCURRENT
is described as:
Characteristic value signifying that the element source may be safely concurrently modified (allowing additions, replacements, and/or removals) by multiple threads without external synchronization. If so, the Spliterator is expected to have a documented policy concerning the impact of modifications during traversal.
From all these documentations, and being consistent with the concurrency model of the ConcurrentHashMap
, it means that the stream pipeline is completely thread-safe and will traverse the elements as they existed upon the creation of the iterator.
Upvotes: 9