Существует ли HashMap с методом getAndWait ()? Например. реализация BlockingConcurrentHashMap? - PullRequest
9 голосов
/ 17 июня 2011

Многие потоки могут заполнять HashMap, в некоторых случаях мне нужно подождать (заблокировать), пока объект не существует в HashMap, например:

BlockingConcurrentHashMap map = new BlockingConcurrentHashMap();
Object x = map.getAndWait(key, 1000);    //(object_to_get, max_delay_ms)

Интересно, если такая вещь уже существует, я ненавижу заново изобретать колеса.

Ответы [ 5 ]

4 голосов

Blockingmap4j удовлетворит вашим требованиям.
Вы можете найти его на https://github.com/sarveswaran-m/blockingMap4j/wiki/
Поскольку в реализации используются гранулярные блокировки, производительность не будет сильно ухудшена.

PS
Это довольно поздний ответ на вопрос, которому 2 года. Поскольку нет возможности отправить личное сообщение автору вопроса, отвечаю здесь.

4 голосов
/ 17 июня 2011

Насколько я знаю, «Карта трансфера» недоступна.Хотя его создание в теории не так уж сложно.

public class TransferMap<K,V> implements Map<K,V>{
  @GuardedBy("lock")
  private final HashMap<K,V> backingMap = new HashMap<K,V>();

  private final Object lock = new Object();
  public V getAndWait(Object key){
     synchronized(lock){
       V value = null;
         do{
            value = backingMap.get(key);

            if(value == null) lock.wait();

         }while(value == null); 
      }
      return value;
     }
   public V put(K key, V value){
      synchronized(lock){
         V value = backingMap.put(key,value);
         lock.notifyAll();
      }
     return value;
   }
  }

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

3 голосов
/ 17 июня 2011

Улучшение impl Джона, с целевым уведомлением (), вместо "гремящего стада", что особенно плохо, когда никто не ждет вставленного ключа

HashMap<K,Object> locks = new HashMap<>();

put(key, value)
    synchronized(locks)
        backingMap.put(key,value);

        lock = locks.get(key);
        if(lock!=null)
            lock.notifyAll();

getAndWait(key)
    // not hard, but pretty verbose
1 голос
/ 17 июня 2011

Вы можете заполнить Hashtable с java.util.concurrent.FutureTask<ObjReturned> с самого начала всеми задачами, которые вам нужно вычислить.Затем вы используете пул потоков, чтобы начать выполнение FutureTask s.Вы можете получить результаты асинхронно с помощью ObjReturned obj = hashtable.get(key).get(), который будет ждать, если вопрос FutureTask еще не завершен.

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

0 голосов
/ 17 июня 2011

Я не уверен, какой у вас вопрос. Хотите дождаться значения, когда его нет на карте? Требуется шаблон «производитель-потребитель» BlockingQueue на карте. Если это так, то я не знаю ничего подобного ни в JRE, ни где-либо еще.

Google guava MapMaker позволяет создавать вычислительную карту, то есть карту, которая создает значение, если оно не существует, с помощью фабрики с типом Function . Если несколько потоков достигают этой ситуации одновременно, один создает значение, а остальные блоки ожидают его. Я знаю, что это не производитель-потребитель, но это то, что я могу предложить.

...