Подтвердить что ты не робот

У java есть структура данных LinkedConcurrentHashMap?

Мне нужна структура данных, которая является LinkedHashMap и является потокобезопасной.

Как я могу это сделать?

4b9b3361

Ответ 1

Вы можете обернуть карту в Collections.synchronizedMap, чтобы получить синхронизированный хэш файл, который поддерживает порядок вставки. Это не так эффективно, как ConcurrentHashMap (и не реализует дополнительные методы интерфейса ConcurrentMap), но он действительно дает вам (несколько) потокобезопасное поведение.

Даже могучие Google Collections, похоже, пока не решили эту проблему. Однако существует один проект, который пытается решить проблему.

Я говорю несколько о синхронизации, потому что итерация по-прежнему не является потокобезопасной в том смысле, что могут возникать исключения параллельной модификации.

Ответ 2

Существует несколько разных подходов к этой проблеме. Вы можете использовать:

Collections.synchronizedMap(new LinkedHashMap());

как предложили другие ответы, но у этого есть несколько ошибок, о которых вам нужно знать. Наиболее важно то, что вам часто нужно хранить синхронизацию коллекций при повторении коллекции, что, в свою очередь, предотвращает доступ других потоков к коллекции до тех пор, пока вы не завершите ее повторение. (См. теорию и практику Java: параллельные классы коллекций). Например:

synchronized(map) {
    for (Object obj: map) {
        // Do work here
    }
}

Используя

new ConcurrentHashMap();

вероятно, лучший выбор, так как вам не нужно блокировать сборку, чтобы перебирать ее.

Наконец, вы можете рассмотреть более функциональный подход к программированию. То есть вы можете считать карту по существу неизменной. Вместо добавления к существующей карте вы должны создать новую, содержащую содержимое старой карты плюс новое дополнение. Сначала это звучит довольно странно, но на самом деле это способ Scala имеет дело с concurrency и коллекциями

Ответ 3

Существует одна реализация, доступная в коде Google. Цитата со своего сайта:

Высокопроизводительная версия java.util.LinkedHashMap для использования в качестве кеша программного обеспечения.

Дизайн

  • Сопутствующий связанный список запускается через ConcurrentHashMap для обеспечения порядка выселения.
  • Поддерживает вставку и доступ к упорядоченным политикам выселения (FIFO, LRU и Second Chance).

Ответ 4

Вы можете использовать ConcurrentSkipListMap, доступный только в Java SE/EE 6 или более поздней версии. Это упорядоченный заказ в том, что ключи сортируются в соответствии с их естественным порядком. Вы должны иметь Компаратор или сделать ключи Сопоставимые объекты. Чтобы имитировать связанное поведение карты хэша (порядок итерации - это порядок времени, в который были добавлены записи), я реализовал свои ключевые объекты, чтобы всегда сравнивать их больше, чем заданный другой объект, если он не равен (что бы ни было для вашего объекта). Обернутой синхронизированной связанной хэш-карты недостаточно, поскольку, как указано в http://www.ibm.com/developerworks/java/library/j-jtp07233.html: "Синхронизированные коллекции обложек, synchronizedMap и synchronizedList иногда называются условно потокобезопасными - все отдельные операции являются потокобезопасными, но последовательности операций, в которых поток управления зависит от результатов предыдущих операций, могут быть подвергнуты расам данных. В первом фрагменте в листинге 1 показан общий put-if-absent idiom - если запись еще не существует на карте, добавьте его. К сожалению, как написано, другой поток может вставить значение с тем же ключом между тем, как будет возвращен метод containsKey(), и временем, когда вызывается метод put(). Если вы хотите, после вставки вам нужно обернуть пару операторов синхронизированным блоком, который синхронизируется на карте m."

Так что только помощь - это ConcurrentSkipListMap, которая в 3-5 раз медленнее, чем обычная ConcurrentHashMap.

Ответ 5

Collections.synchronizedMap(new LinkedHashMap())

Ответ 6

Так как ConcurrentHashMap предлагает несколько важных дополнительных методов, которых нет в интерфейсе карты, просто перенос LinkedHashMap с помощью synchronizedMap не даст вам такой же функциональности, в частности, они не дадут вам ничего подобного putIfAbsent (), замените (key, oldValue, newValue) и удалите (key, oldValue) методы, которые делают ConcurrentHashMap настолько полезными.

Если нет какой-либо библиотеки apache, которая реализовала то, что вы хотите, вам, вероятно, придется использовать LinkedHashMap и предоставить соответствующие синхронизированные {} блоки.

Ответ 7

Я просто попробовал синхронизованную ограниченную карту LRU на основе порядка вставки LinkedConcurrentHashMap; с Блокировка чтения/записи для синхронизации. Поэтому, когда вы используете итератор; вам необходимо приобрести WriteLock, чтобы избежать ConcurrentModificationException.
Это лучше, чем Collections.synchronizedMap.

public class LinkedConcurrentHashMap<K, V> {

    private LinkedHashMap<K, V> linkedHashMap = null;
    private final int cacheSize;  
    private ReadWriteLock readWriteLock = null;

    public LinkedConcurrentHashMap(LinkedHashMap<K, V> psCacheMap, int size) {
        this.linkedHashMap  = psCacheMap;
        cacheSize = size;
        readWriteLock=new ReentrantReadWriteLock();
    }

    public void put(K key, V value) throws SQLException{
        Lock writeLock=readWriteLock.writeLock();
        try{
            writeLock.lock();
            if(linkedHashMap.size() >= cacheSize && cacheSize > 0){
                K oldAgedKey = linkedHashMap.keySet().iterator().next();
                remove(oldAgedKey);
            }
            linkedHashMap.put(key, value);
        }finally{
            writeLock.unlock();
        }
    }

    public V get(K key){
        Lock readLock=readWriteLock.readLock();
        try{
            readLock.lock();
            return linkedHashMap.get(key);
        }finally{
            readLock.unlock();
        }
    }

    public boolean containsKey(K key){
        Lock readLock=readWriteLock.readLock();
        try{
            readLock.lock();
            return linkedHashMap.containsKey(key);
        }finally{
            readLock.unlock();
        }
    }

    public V remove(K key){
        Lock writeLock=readWriteLock.writeLock();
        try{
            writeLock.lock();
            return linkedHashMap.remove(key);
        }finally{
            writeLock.unlock();
        }
    }

    public ReadWriteLock getLock(){
        return readWriteLock;
    }

    public Set<Map.Entry<K, V>> entrySet(){
        return linkedHashMap.entrySet();
    }
}

Ответ 8

Ответ в значительной степени нет, нет ничего эквивалентного сопоставлению ConcurrentHashMap (например, LinkedHashMap). Как отмечали другие люди, вы можете обернуть свою коллекцию с помощью Collections.synchronizedMap(-yourmap-), однако это не даст вам такой же уровень мелкозернистой блокировки. Он просто блокирует всю карту при каждой операции.

Лучше всего использовать синхронизацию вокруг любого доступа к карте (там, где это имеет значение, конечно. Возможно, вам неважно, грязные чтения) или написать обертку вокруг карты, которая определяет, когда это необходимо или не следует блокировать.