Search code examples
javamultithreadingqueueconcurrenthashmap

Thread safe Map of Queues


I want to implement a thread safe Map of Queues.

I intent to start with an empty Map. If the key does not exist, I want to create a new Map entry with a new Queue. If the key does exist, I want to add to the Queue. My proposed implementation is as follows:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

public class StackOverFlowExample {

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

    public void addElementToQueue(String key, String value){
        if (map.containsKey(key)){
            map.get(key).add(value);
        }
        else{
            ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
            queue.add(value);
            map.put(key, queue);
        }           
    }    
}

My concern is that is when multiple threads attempt to add a new value to the Map, the first will put a new Map entry with a new Queue, the second will wait, and then put a new Queue for the key, rather than adding to the Queue. My concurrency / concurrency API knowledge is slim at best. Perhaps the concurrency is in-place to avoid this? Advice would be much appreciated.


Solution

  • This pattern has probably been posted many times on SO (efficiently adding to a concurrent map):

    Queue<String> q = map.get(key);
    if(q == null) {
      q = new ConcurrentLinkedQueue<String>();
      Queue<String> curQ = map.putIfAbsent(key, q);
      if(curQ != null) {
        q = curQ;
      }
    }
    q.add(value);
    

    Note that since Java 8, this can be replaced with computeIfAbsent().