Есть ли в java потокобезопасная и уникальная для элементов очередь?

Как гибрид ConcurrentHashMap и ConcurrentLinkedQueue.

Вот мои требования:
Мне нужна асинхронная обновляемая система кэширования. Это означает, что я оборачиваю каждый объект, прежде чем помещать его в кэш памяти. В варпере есть метка времени, которая указывает, когда истечет срок его содержимого. Каждый запрос с внешней стороны будет извлекать данные из кэша памяти, и если варппер показывает срок действия, будет сгенерировано событие обновления, которое будет помещено в concurrentLinkedQueue, а затем будет ожидать асинхронного обновления.
Проблема в том, что я не хочу обновлять объект более одного раза напрасно. Прежде чем добавлять событие в очередь, я хочу найти способ убедиться, что в очереди уже нет события для того же объекта.

Это нормально, если я сделаю это таким образом?

1. Создайте класс warpper, он содержит хэш-карту и связанный список. Весь его метод синхронизирован:

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. Если мне нужно действие «опрос», итератор элемента из него.

public Object poll(){
    Collection valueColl = concurrentHashMap.values();
    if(valueColl.isEmpty()){
        retrun null;
    }
    return valueColl.get(0);
}  

Действие concurrentHashMap.values().get(0) медленное или нет?

3. Просмотрите исходный код "ConcurrentHashMap" и "ConcurrentLinkedQueue", а затем, если возможно, напишите "ConcurrentUniqueLinkedQueue".
На данный момент это выглядит немного сложно для меня.

Итак, как бы вы сказали, ребята?


person watchzerg    schedule 01.02.2013    source источник
comment
Я считаю, что это решение будет очень медленным. ты пробовал? На мой взгляд, должно быть не так уж и плохо. Все операции в методе add довольно быстрые. Также я думаю, что это довольно чистое решение. Но я бы заменил hashMap на hashSet, потому что на самом деле здесь нет hashMap.   -  person Mikita Belahlazau    schedule 01.02.2013
comment
Вы проверили Guava API docs.guava-libraries.googlecode.com/git /javadoc/index.html ? @Nikita на самом деле HashSet использует HashMap внутри. Более того, я читал документацию по EHCache или Hazelcast. Вы можете найти то, что вам нужно. Не изобретайте велосипед.   -  person Piotr Gwiazda    schedule 01.02.2013
comment
@PiotrGwiazda Я знаю это по HashMap. Но для ясности мне здесь больше нравится HashSet.   -  person Mikita Belahlazau    schedule 01.02.2013
comment
@Никита конечно ты прав.   -  person Piotr Gwiazda    schedule 01.02.2013
comment
если вы используете HashMap (или hashSet) для проверки существования события, не забудьте удалить его после put(), иначе вскоре у вас будет утечка памяти. HashMap/Set будет содержать сильную ссылку на объекты, и они никогда не будут GCed.   -  person Bimalesh Jha    schedule 01.02.2013


Ответы (1)


Я не думаю, что вы хотите отказаться от последних обновлений. Возможно, вы усложняете задачу больше, чем нужно.

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;
}

Это даст вам последнее значение для ключа в порядке очереди. Ему не нужна блокировка.

person Peter Lawrey    schedule 01.02.2013
comment
Что ж, хорошее решение, я думаю, оно сработает. Большое спасибо @PeterLawrey - person watchzerg; 02.02.2013
comment
@watchzerg Обратите внимание, я исправил это. - person Peter Lawrey; 02.02.2013