像“ConcurrentHashMap”和“ConcurrentLinkedQueue”的混合体。
这是我的要求:
我需要一个异步更新的缓存系统。这意味着我在将每个实体设置为memcache之前将其包装起来。 warpper中有一个时间戳,指示其内容何时到期。前端的每个请求都将从memcache中获取数据,如果warpper显示过期,则会生成更新事件并将其放入concurrentLinkedQueue,然后等待异步更新。
问题是:我不想徒劳地更新一个实体。在将事件添加到队列之前,我希望找到一种方法来确保队列中的同一实体没有事件。
如果我以这些方式做到,那可以吗?
1,创建一个warpper类,它包含一个hashMap和一个linkedList。它的所有方法都是同步的:
public synchronized boolean add(String key,Object value){
if(hashMap.containsKey(key)){
return false;
}else{
hashMap.put(key,value);
return linkedList.offer(value);
}
}
我相信这个解决方案会非常慢 也许它就像Collections.synchronizedMap(new LinkedHashMap())。
2,只需使用concurrentHashMap。如果我需要“poll”动作,则从中迭代一个元素。
public Object poll(){
Collection valueColl = concurrentHashMap.values();
if(valueColl.isEmpty()){
retrun null;
}
return valueColl.get(0);
}
行动concurrentHashMap.values().get(0)
是否缓慢?
3,查看“ConcurrentHashMap”和“ConcurrentLinkedQueue”的源代码,如果可能,写一个“ConcurrentUniqueLinkedQueue”。
这对我来说现在看起来有点困难。
所以,你们怎么说?
答案 0 :(得分:5)
我不认为你想丢弃最新的更新。也许你使它变得比它需要的更复杂。
public void add(K key, V value) {
concurrentMap.put(key, value);
queue.add(key);
}
public V poll() {
for(K key; (key = queue.take()) != null;) {
V value = concurrentMap.remove(key);
if (value != null)
return value;
// value will be null if it's a duplicate so ignore and look for more.
}
return null;
}
这将为您提供排队顺序键的最新值。它不需要任何锁定。
答案 1 :(得分:0)
import java.util.LinkedHashSet;
import java.util.Queue;
import java.util.concurrent.locks.ReentrantLock;
public class ConcurrentSetQueue<E> extends LinkedHashSet<E> implements Queue<E> {
/**
*
*/
private static final long serialVersionUID = 7906542722835397462L;
final java.util.concurrent.locks.ReentrantLock lock = new ReentrantLock();
public E remove() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
E next = iterator().next();
remove(next);
return next;
} finally {
lock.unlock();
}
}
@Override
public E element() {
return iterator().next();
}
@Override
public boolean offer(E arg0) {
return add(arg0);
}
@Override
public E peek() {
return element();
}
@Override
public E poll() {
return remove();
}
}