I have a ConcurrentMap<String, SomeObject> object. I want to write a method that would return the SomeObject value if it exists, or create a new SomeObject, put it in the Map, and return it if it doesn't exist.
Ideally, I could use ConcurrentMap's putIfAbsent(key, new SomeObject(key))
, but that means that I create a new SomeObject(key) each time, which seems very wasteful.
So I resorted to the following code, but am not sure that it's the best way to handle this:
public SomeValue getSomevalue(String key){
SomeValue result = concurrentMap.get(key);
if (result != null)
return result;
synchronized(concurrentMap){
SomeValue result = concurrentMap.get(key);
if (result == null){
result = new SomeValue(key);
concurrentMap.put(key, result);
}
return result;
}
}
Ideally, I could use ConcurrentMap's putIfAbsent(key, new SomeObject(key)), but that means that I create a new SomeObject(key) each time, which seems very wasteful.
Then use computeIfAbsent
:
concurrentMap.computeIfAbsent(key, SomeObject::new);
Using synchronized
with a ConcurrentMap doesn't prevent other threads from performing operations on the map in the middle of the synchronized
block. ConcurrentMap doesn't promise to use the map's monitor for synchronization, and neither ConcurrentHashMap nor ConcurrentSkipListMap synchronize on the map object.
Note that the ConcurrentMap interface doesn't promise that the value will only be computed once, or that the value won't be computed if the key is already present. ConcurrentHashMap makes these promises, but ConcurrentSkipListMap doesn't.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With