I need to update a value in a ConcurrentHashmap but I am not sure on how to do this thread safe.
The Hashmap is a ConcurrentHashMap and I need to get the instance of the custom class, perform some operations on it and then put the updated value back in.
Is there any way to combine this get-alter-put operation to something atomic?
Thanks in advance
A ConcurrentHashMap 's computeIfPresent
method is a possibility. From the javadocs: If the value for the specified key is present, attempts to compute a new mapping given the key and its current mapped value. The entire method invocation is performed atomically ( expects that computation should be short and simple ).
How does the method work, in general? Some example code:
Consider a Map<String, Integer>
map
with keys and values: {four=4, one=1, ten=10, two=2, three=3, five=5, eleven=11}
(1) updates the mapping with new value (note the lambda is a BiFunction returning a newly computed value):
map.computeIfPresent("ten", (k, v) -> new Integer(100));
(2) the function returns a null, the existing mapping is removed:
map.computeIfPresent("eleven", (k, v) -> null);
(3) the mapping is not added, as there is no existing mapping:
map.computeIfPresent("twenty", (k, v) -> new Integer(20));
EDIT:
Note on compute()
: Using the same input map
data (and method arguments), the compute
method works similarly but for the case 3. Note the case 3 where new mappings can be added:
(3) a new mapping is added.
You can use ConcurrentHashMaps computeIfPresent https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#computeIfPresent-K-java.util.function.BiFunction-
But since computeIfPresent is a costly operation as its atomic and some update operations will be blocked by other threads during the computation of the BiFunction . You can preclude this with a read operation on concurrent hashmap which is pretty fast and if that returns not null , invoke computeIfPrsent
Below code gets the value of key "1" and adds 100 to it and puts in back to the map in a atomic way
ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
map.put(1,100);
Integer value = map.get(1);
if (value != null)
map.computeIfPresent(1, (key, oldValue) -> oldValue + 100);
}
I would say you can use
map.compute(key, (k,v) -> {
if(k != null) {
return v+1;
} else {
return some_var;
}
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.