这种模式可能已在SO上多次发布(有效地添加到并发映射):
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);
所以你担心线程A和线程B将执行以下操作:
thread A: lock ConcurrentHashMap Look for Queue "x" (not found) unlock ConcurrentHashMap create Queue "x" lock ConcurrentHashMap Insert Queue X unlock ConcurrentHashMap Thread B: Lock ConcurrentHashMap (while thread A is in 'create Queue X') look for queue X (not found) unlock ConcurrentHashMap (thread A then gets lock) create Queue "x" v2 lock ConcurrentHashMap Insert Queue X v2 (overwriting the old entry) unlock ConcurrentHashMap
这实际上是一个真正的问题,但通过使AddElementToQueue成为同步方法可以轻松解决这个问题。然后在任何给定时间内AddElementToQueue中只能有一个线程,因此第一个'unlock'和第二个'lock'之间的同步孔关闭。
从而
public synchronized void addElementToQueue(String key, String value){
应该解决你的丢失队列问题。
如果Java 8是一个选项:
public void addElementToQueue(String key, String value) { map.merge(key, new ConcurrentLinkedQueue<>(Arrays.asList(value)), (oldValue, coming) -> { oldValue.addAll(coming); return oldValue; }); }