我有一个Map<String, Queue<?>>
每次我必须放置几个(键,值)时,我都需要获取与该键关联的非线程安全队列并向其添加一个值(如果键存在)。因为我需要更新现有值(队列),所以我认为最好的方法是使用 ReentrantLock(Java < 1.5 中的同步块(synchronized block)或同步(对象))而不是 ConcurrentHashMap。
这是正确的还是我可以使用 ConcurrentHashMap 而不是 HashMap + Lock?我认为 ConcurrentHashMap 在 get 操作中更有效,但我不知道这里是否是正确的解决方案。
private static ReentrantLock lock_Vqueue = new ReentrantLock();
private static HashMap<String,Queue<DocumentObjectHolder>> cacheData = new HashMap<String,Queue<DocumentObjectHolder>>();
/**
* insert element in the tail
* sort the elements by priority
* @param obj a DocumentObjectHolder Object
*/
public static void add(String key, DocumentObjectHolder obj){
ReentrantLock lock = lock_Vqueue; //performance side effect
try{
Queue<DocumentObjectHolder>priorityProcessingVirtualQueue;
lock.lock();
if (!cacheData.containsKey(key)){
priorityProcessingVirtualQueue = new PriorityQueue<DocumentObjectHolder>(1, new PriorityComparator());
cacheData.put(key, priorityProcessingVirtualQueue);
}
priorityProcessingVirtualQueue = cacheData.get(key);
priorityProcessingVirtualQueue.add(obj);
cacheData.put(key, priorityProcessingVirtualQueue);
}finally {
lock.unlock();
}
}
/**
*
* @return DocumentObjectHolder instance from head of list (FIFO)
*/
public DocumentObjectHolder get(String key){
ReentrantLock lock = lock_Vqueue; //performance side effect
Queue<DocumentObjectHolder>priorityProcessingVirtualQueue;
try {
lock.lock();
if (cacheData.containsKey(key)){
priorityProcessingVirtualQueue = cacheData.get(key);
return priorityProcessingVirtualQueue.poll();
}
return null;
}finally{
lock.unlock();
}
}
}
这段代码是否正确或者可以提高性能吗?
最佳答案
因此,您有两个需要同步的独立原子指令。
- 将新队列放入 map
- 将对象放入队列
这是我的建议。
继续使用
ConcurrentHashMap
。您仍然需要放入
到 map 中,您也可以使用 CHM 安全地完成此操作。使用
BlockingQueue
。在这种情况下,您可以使用PriorityBlockingQueue
。如果您无法执行 (2),则从 map 在队列上
同步
。
所以 1 和 3 看起来像:
public static void add(String key, DocumentObjectHolder obj){
Queue<DocumentObjectHolder> priorityProcessingVirtualQueue= cacheData.get(key);
if(priorityProcessingVirtualQueue== null){
Queue<DocumentObjectHolder> temp = new PriorityQueue<DocumentObjectHolder>(1, new PriorityComparator());
queue = cacheData.putIfAbsent(key, temp);
if(priorityProcessingVirtualQueue== null){
priorityProcessingVirtualQueue= temp;
}
}
synchronized(priorityProcessingVirtualQueue){
priorityProcessingVirtualQueue.add(obj);
}
}
1 和 2 所需的唯一区别是缺少 synchronized
。
我们之所以知道这是线程安全的,是因为即使有 2 个或更多线程输入 if(queue == null)
,也只有一个线程会在 putIfAbsent
中成功。失败的线程将分配queue
以等于成功放入的队列。如果一个线程获胜(queue == null为真),那么我们将分配该队列为我们的队列 创建(我们是获胜线程)。
关于java - 在我的情况下是 Lock+HasMap 还是 ConcurrentHashMap?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30169932/