Search code examples
javaconcurrencyconcurrenthashmapcopyonwritearraylist

concurrent hashmap and copyonwritearraylist


I am trying to populate a cache which hold the key/value with ConcurrentHashMap.

I am assuming using a CopyOnWriteArrayList takes care of concurrency and I have that as my value for my key, but I am missing something in the below code and it is overriding its values when multiple threads are executing.

if (testMap.get(id) == null) {
   CopyOnWriteArrayList<String> copyArr = new CopyOnWriteArrayList<String>();
   copyArr.add("Add Value");
   testMap().putIfAbsent(id, copyArr);
} else {                    
   testMap.put(id,testMap.get().add("Append Value"));
}

How do I protect the code which creates the CopyOnWriteArrayList from multiple threads.

Here is the revised version of code as per the suggestions below.

CopyOnWriteArrayList<Subscriber> subscriberArr =  CacheUtils.getSubscriberMap().get(syncDet.getCardNumber());

if (subscriberArr == null) {

subscriberArr = new CopyOnWriteArrayList<Subscriber>();
CopyOnWriteArrayList<Subscriber> refArr = 

cacheUtils.getSubscriberMap().putIfAbsent(syncDet.getCardNumber(), subscriberArr);

if (refArr != null) {
 subscriberArr = refArr;
}

}
 subscriberArr.add(syncDet.getSubScriber());

On iterating the subscriber map i dont see a value object. size is 0 .


Solution

  • You need to first retrieve the appropriate list then populate it. Something like:

    List<String> copyArr = testMap.get(id);
    if (copyArr == null) {
        copyArr = new CopyOnWriteArrayList<String>();
        List<String> inMap = testMap.putIfAbsent(id, copyArr);
        if (inMap != null) copyArr = inMap; // already in map
    }
    copyArr.add("Add Value");
    

    That way you only put a new list in the map if there wasn't already one and you add your item to whatever list has made it to the map.