2013-04-26 2 views
3

Мне нужна реализация карты , которая поддерживает параллелизм и сохраняет только наименьшую/большую добавленную стоимость (в зависимости от компаратора). Будет ли работать следующий код?Скользящая карта с наименьшим значением

class LeastValConcurrentMap<K, V> { 

    //put the least value 
    private final Comparator<V> comparator; 
    private final ConcurrentHashMap<K, V> map = new ConcurrentHashMap<K, V>(); 

    LeastValConcurrentMap(Comparator comparator) { 
    this.comparator = comparator; 
    } 

    public void put(K k, V v) { 
    V vOld = map.put(k, v); 
    if (vOld == null || comparator.compare(v, vOld) <= 0) //i.e. v <= vOld so better 
     return; 
    //recursively call self 
    put(k, vOld); 
    } 

    @Override 
    public String toString() { 
    return map.toString(); 
    } 
} 

Не могли бы вы привести пример того, где/почему это не сработает? Есть ли что-то в guava или стандартной java-библиотеке, которую я мог бы использовать?

+0

Я считаю, что вы хотите V VOLD = map.get (k, v); –

+0

вам необходимо синхронизировать метод LeastValConcurrentMap .put (K k, V v), поскольку ConcurrentHashMap может быть потокобезопасным, но ваш метод не является. –

+0

У вас есть состояние гонки. Рассмотрим, что происходит, когда два потока одновременно вводят один и тот же ключ. т.е. они оба запускают put() –

ответ

0

Возможно, вам потребуется синхронизировать метод put класса LeastValConcurrentMap. Кажется, вы только кладете ценности на карту .. где/как эти значения будут использоваться. Чтобы обеспечить параллельный доступ, вам нужно подумать об операциях чтения и записи. Кроме того, последняя строка вашего метода пут должна быть как map.put (к, VOLD)

+0

Обратите внимание, что мой метод рекурсивный –

+0

не могли бы вы объяснить, почему он должен быть рекурсивным? –

+0

ему нужно еще раз проверить, если другая нить вложила в него более низкое значение –

2

Я думаю, что это более сложное, вам нужно использовать атомным ConcurrentHashMap.replace(K key, V oldValue, V newValue)

public void put(K k, V v) { 
    V oldValue = map.putIfAbsent(k, v); 
    if (oldValue == null) { 
     // this is the first mapping to this key 
     return; 
    } 
    for (;;) { 
     if (comparator.compare(v, oldValue) <= 0) { 
      break; 
     } 
     // this replace returns true only if oldValue was replaced with new value atomically 
     if (map.replace(k, oldValue, v)) { 
      break; 
     } 
     // otherwise another attempt 
     oldValue = map.get(k); 
    } 
+0

выглядит неплохо, я не уверен относительно линии компаратора в вашем ответе, если он не будет comparator.compare (oldValue, v) <= 0 (старое значение лучше, так что перерыв) –

+0

Но я просто взял тот из вашего кода :), конечно, измените в соответствии с требуемой логикой –

+0

Не знаю, заметили ли вы рекурсию в моем коде? можете ли вы привести мне пример, где моя не будет работать –

Смежные вопросы