I have a requirement to have key value pairs, where the value can be a set. This data structure should be thread safe to add remove elements to the set in a multi threaded environment.
My requirement is to create a subscription list, here people can subscribe for different topics. This subscription list should be concurrent, thread safe and fast. I was thinking about Using ConcurentHashMap and ConcurrentHashSet, this will not help me since, I have to put the syncronization block at the top level and it will block the entire map until the put/remove operation completes.
There is no pre-rolled solution, but it is possible to achieve thread-safe concurrency for simple values using a ConcurrentMap<K, Set<V>>
which has Set<V>
values made from ConcurrentMap<V, Boolean>
using Collections.newSetFromMap(Map<V,Boolean>)
.
Then, to get each value set in an atomic way, use ConcurrentMap.computeIfAbsent(K, Function<? super K, ? extends Set<V>>)
:
ConcurrentMap<String, Set<Integer>> multimap = new ConcurrentHashMap<>();
Set<Integer> fooValues = multimap.computeIfAbsent("foo", key -> Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>()));
If you want your values to have a stable iteration order, you can use a ConcurrentSkipListSet
to hold values instead:
ConcurrentMap<String, NavigableSet<Integer>> multimap = new ConcurrentHashMap<>();
NavigableSet<Integer> fooValues = multimap.computeIfAbsent("foo", key -> new ConcurrentSkipListSet<>());
Likewise, in order to remove Set<V>
value holder instances in a thread-safe fashion, you can use ConcurrentMap.computeIfPresent(K, BiFunction<? super K,? super Set<V>,? extends Set<V>>)
:
public static <K, V> void remove(final ConcurrentMap<K, Collection<? extends V>> multimap, final K key,
final V value) {
multimap.computeIfPresent(key, (k, oldValues) -> {
final Collection<? extends V> newValues;
if (oldValues.remove(value) && oldValues.isEmpty()) {
// Remove the empty set from the multimap
newValues = null;
} else {
newValues = oldValues;
}
return newValues;
});
}
Note that there is no " ConcurrentHashSet
" class provided by the Java core libraries .
you write "the value can be a set", but don't mention what the key is. In any case, Hashtable, the first map that was present in Java, is thread safe wrt adding/removing/replacing key,value pairs.
You can create a thread-safe Set with one of the methods described here . Whether that set is stored as value in an hashmap makes no difference.
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.