2012-06-19 2 views
9

Сейчас я пытаюсь создать поток производителя/потребителя, поток производителя проходит через все возможные комбинации букв и создает их соответствующие хеши MD5. Затем каждая комбинация и ее хэш помещаются в HashMap<String,String>. Теперь в моем потребительском потоке я хочу иметь возможность использовать коллекцию Queue<> на хэшмапе, чтобы мой потребительский поток мог вызвать poll() и т. Д., Таким образом удаляя значения atc как Queue, но все же предоставляя мне возможность видеть как комбинацию, так и ее хэш при вызове poll() Как мне это сделать? У меня есть HashMap, но я не знаю, как «сделать» или бросить его как очередь. Спасибо.Возможно ли создать очередь для набора HashMap?

ответ

7

Вы не должны использовать HashMap, не обращаясь к потокобезопасности вашего кода. Кроме того, вы можете завершить Live-Lock.

Чтобы иметь возможность выполнять итерацию вашей карты с помощью порядка, в который были вставлены ключи, вы можете использовать LinkedHashMap.

Map m = Collections.synchronizedMap(new LinkedHashMap(...)); 

продюсер подтолкнет записи, как это (ничего особенного):

m.put(key, object) 

Потребитель будет опрашивать записи, как это:

while (someCondition) { 
    Map.Entry nextEntry = null; 

    // This block is equivalent to polling 
    { 
     synchronized(s) { 
      Iterator i = s.iterator(); // Must be in the synchronized block 
      if (i.hasNext()) { 
       nextEntry = i.next(); 
       i.remove(); 
      } 
     } 
    } 

    if (nextEntry != null) { 
     // Process the entry 
     ... 
    } else { 
     // Sleep for some time 
     ... 
    } 
    // process 
} 
+0

Спасибо, что это сработало шармом и было быстрым, легким и понятным для реализации –

5

Тип LinkedHashMap подобна комбинации HashMap и Queue - она ​​хранит пары ключ/значение, но и запоминает порядок, в котором они были вставлены. Это может быть именно тот тип, который вы ищете. Нет явной функции poll(), но если вы получите итератор над LinkedHashMap, вы увидите элементы в том порядке, в котором они были добавлены. Возможно, вы могли бы затем написать такую ​​функцию:

public <KeyType, ValueType> KeyType first(LinkedHashMap<KeyType, ValueType> map) { 
    assert !map.isEmpty(); 
    return map.iterator().next(); 
} 

, которая вернет вам первый элемент. Просто убедитесь, что вы правильно синхронизировали.

В качестве альтернативы вы можете просто сохранить пары ключ/значение внутри Queue, указав вспомогательный класс Pair, а затем сохраните Pair с в очереди.

Надеюсь, это поможет!

+0

Ницца, так что он будет просто нужно некоторое SyncObject к сигнал, когда можно читать с LinkedHashMap на стороне потребителя. –

+0

Привет, LinkedHashMap не является потокобезопасным, и это не тип Queue. – sperumal

+0

@ sperumal - я никогда не намекал, что это так. Я предположил, что OP предоставит код синхронизации. Кроме того, я не считаю, что существует какое-либо требование о том, что он должен быть типа 'Queue'; вопрос ОП никогда не упоминает об этом. Если это требование, то этот подход определенно не сработает. – templatetypedef

4

Я предлагаю вам создать очереди EntrySet -

Queue<EntrySet<String,String>> queue = new SynchronousQueue<EntrySet<String,String>>(); 
for (EntrySet<String,String> entry:map.entrySet()) { 
    queue.add(entry); 
} 

Вы можете использовать другой тип очереди, которая позволяет поместить элементы, и только prdocuer ждет в случае не пусто, таких как LinkedBlockingQueue.
Затем продюсер сможет перекомпоновать карту на основе объектов EntrySet, если это необходимо.

+0

Хм это похоже на хороший метод. Спасибо, я попробую. Один из вопросов касается этой потоковой безопасности? –

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