I am using JAVA 8 and trying to modify a final Map , problem is that map is serving the live transformation logic so if i try to clear it and then modify it ,there will be some missed transformation
private final Map<String, Set<EventMapping>> registeredEvents = new ConcurrentHashMap<>();
Map<String, Set<EventMapping>> newRegisteredEntries = eventMappingDBWrapper.getActiveEventMapping();
if (MapUtils.isNotEmpty(newRegisteredEntries)) {
registeredEvents.clear();
registeredEvents.putAll(newRegisteredEntries);
}
My concern is if i call clear()
then map will be empty untill putAll()
is called in the next line , and in the mean time if some events need fetching of these mappings ,it will create problem , as we are processing 1M event per minute.
Is there any way to safely execute it ?
CodePudding user response:
If the change must happen atomically, in a critical region, though not blocking for reads, you'll need a special datastructure.
However the following might do:
if (MapUtils.isNotEmpty(newRegisteredEntries)) {
Set<String> oldKeys = new HashSet<>(registeredEvents.keySet());
oldKeys.removeAll(newRegisteredEntries.keySet());
registeredEvents.putAll(newRegisteredEntries);
oldKeys.forEach(registeredEvents::remove);
}
A variation would be to fill oldKeys
afterwards.
This still has a huge drawback: concurrent writes, like calling this function twice will introduce a bit of garbage. Also the change is not atomic, and combining transformations on several keys may result in old and one transformations being mixed.
Should you need some better concurrency behavior (java.util.concurrent
), determine your requirements, write the API methods first, and then see for an implementation. With an orchestrated multiple change, where map values of several keys belong together, you might think of something like verion numbers.