Class LoadingMap<K,V>
- Type Parameters:
K-V-
NonBlockingHashMap where all values are wrapped by Future.
The main purpose of this class is to provide the functionality of concurrent hash map which may perform operations like
ConcurrentHashMap.computeIfAbsent(Object, Function) and ConcurrentHashMap.computeIfPresent(Object, BiFunction)
with synchronization scope reduced to the single key - that is, when dealing with a single key, unlike
ConcurrentHashMap we do not lock the whole map for the time the mapping function is running. This may help
to avoid the case when we want to load/unload a value for a key K1 while loading/unloading a value for a key K2. Such
scenario is forbidden in case of ConcurrentHashMap and leads to a deadlock. On the other hand, NonBlockingHashMap
does not guarantee at-most-once semantics of running the mapping function for a single key.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classThrown when unloading a value failed. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionblockingLoadIfAbsent(K key, Supplier<? extends V> loadFunction) If the value for the given key is missing, execute a load function to obtain a value and put it into the map.blockingUnloadIfPresent(K key, Consumer<? super V> unloadFunction) If a value for the given key is present, unload function is run and the value is removed from the map.getIfReady(K key) Get a value for a given key.
-
Constructor Details
-
LoadingMap
public LoadingMap()
-
-
Method Details
-
getIfReady
Get a value for a given key. Returns a non-null object only if there is a successfully initialized value associated, with the provided key. It returnsnullif there is no value for the key, or the value is being initialized or removed. It does not throw if the last attempt to initialize the value failed. -
blockingLoadIfAbsent
If the value for the given key is missing, execute a load function to obtain a value and put it into the map. It is guaranteed that the loading and unloading a value for a single key are executed serially. It is also guaranteed that the load function is executed exactly once to load a value into the map (regardless of the concurrent attempts). In case there is a concurrent attempt to load a value for this key, this attempt waits until the concurrent attempt is done and returns its result (if succeeded). If the concurrent attempt fails, this attempt is retried. However, if this attempt fails, it is not retried and the exception is rethrown. In case there is a concurrent attempt to unload a value for this key, this attempt waits until the concurrent attempt is done and retries loading. When the mapping function returnsnull,NullPointerExceptionis thrown. When the mapping function throws exception, it is rethrown by this method. In both cases nothing gets added to the map. It is allowed to nest loading for a different key, though nested loading for the same key results in a deadlock.- Throws:
RuntimeException
-
blockingUnloadIfPresent
public V blockingUnloadIfPresent(K key, Consumer<? super V> unloadFunction) throws LoadingMap.UnloadExecutionException If a value for the given key is present, unload function is run and the value is removed from the map. Similarly toblockingLoadIfAbsent(Object, Supplier)at-most-once semantics is guaranteed for unload function. When unload function fails, the value is removed from the map anyway and the failure is rethrown. When the key was not found, the method returnsnull.- Throws:
LoadingMap.UnloadExecutionException- when the unloading failed to complete - this is checked exception because the value is removed from the map regardless of the result of unloading; therefore if the unloading failed, the caller is responsible for handling that
-