Java HashMaps with put and get issues - maybe concurrency?

I worked with ConcurrentHashMaps, but I'm not quite sure that this will cover all the bases here.

I have a Spring component. This component will contain a map. It will just be a short link for objects in an external service. If there is no corresponding line on the card, it will make an external service call, get the object and save it in the map. Other classes can then use the mapping for quick search and use. Thus, only put () and get () operations are performed on the map. Records are never deleted.

Speaking of this, I'm a little worried that ConcurrentHashMap cannot provide the atomic control that I need. Retrieving SomeObject from an external service is potentially expensive. I would prefer not to have two separate threads calling almost at the same time, resulting in multiple calls for the same value to the external service.

The idea is this:

Map<String, SomeObject> map = Collections.concurrentHashMap(
    new HashMap<String, SomeObject>());

public SomeObject getSomeObject(String key){
    if (!map.containsKey(key)){
        map.put(key, retrieveSomeObjectFromService(key));
    }
    return map.get(key);

Or that:

Map<String, SomeObject> map = new HashMap<String, SomeObject>();

public SomeObject getSomeObject(String key){
    synchronized(map){
        if (!map.containsKey(key)){
            map.put(key, retrieveSomeObjectFromService(key));
        }
    }
    return map.get(key);
}

, , , , SomeObject. , , , SomeObject, , SomeObjects, , , " , .

+4
1

!

, 1 hashmap. ,

private final ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<String, Object>();
private final ReentrantLock lock = new ReentrantLock();

public Object getSomeObject(String key) {
    Object value = map.get(key);
    if (value == null) {
        try {
            lock.lock();
            value = map.get(key);
            if (value == null) {
                value = retrieveSomeObjectFromService(key);
                map.put(key, value);
            }

        } finally {
            lock.unlock();
        }

    }
    return value;
}

, 2- ? , , , , , .

nullcheck vs contains - , ? .contains, aget, 2 . , .

.. , :

private final ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<String, Object>();

public Object getSomeObject(String key) {
    Object value = map.get(key);
    if (value == null) {
        synchronized (map) {
            value = map.get(key);
            if (value == null) {
                value = retrieveSomeObjectFromService(key);
                map.put(key, value);
            }
        }
    }
    return value;
}
+3

All Articles