i have a main thread that creates a HashMap, adds multiple runnable objects to it and then starts each runnable (passing the HashMap to each). The runnable removes its object from the map just before it is about to finish processing.
I would like to know if there is any reason to use a ConcurrentHashMap (rather than a HashMap) in this case - the only operation the runnables perform on the map is to remove themselves from it. Is there a concurrency consideration that necessitates the use of ConcurrentHashMap in this case?
private final Map<Integer, Consumer> runnableMap = new HashMap<>();
Runnable runnable;
for (int i = 1; i <= NUM_RUNNABLES; i++) {
runnable = new Consumer(i, runnableMap);
runnableMap.put(i, runnable);
executionContext.execute(runnable);
}
private final Integer consumerNumber;
private final Map<Integer, Consumer> runnableMap;
public Consumer(int consumerNumber, final Map<Integer, Consumer> runnableMap){
this.consumerNumber = consumerNumber;
this.runnableMap = runnableMap;
}
public void run() {
:::
// business logic
:::
// Below remove is the only operation this thread executes on the map
runnableMap.remove(consumerNumber);
}
The javadoc of HashMap
says:
Note that this implementation is not synchronized.
If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map.
As mentioned above, deletion is a structural change and you must use synchronization.
Furthermore, in the removeNode()
method of Hashmap (which is called by the remove()
method), the modCount
variable is incremented, which is responsible for ConcurrentModificationException
. So you might get this exception if you remove elements without synchronization.
Therefore you must use a ConcurrentHashMap
.