2012-06-19 13 views
9

W tej chwili próbuję utworzyć wątek producenta/konsumenta, wątek producenta przechodzi przez wszystkie możliwe kombinacje liter i tworzy ich odpowiednie skróty MD5. Następnie każda kombinacja i jej skrót zostanie umieszczony w HashMap<String,String>. Teraz w moim wątku konsumenckim chcę móc używać kolekcji Queue<> na mapie mieszającej, więc mój wątek konsumencki może wywoływać poll() itd., Usuwając w ten sposób wartości atc takie jak Queue, ale nadal daje mi możliwość zobaczenia zarówno kombinacji jak i jej skrótu przy wywoływaniu poll() Jak miałbym to zrobić? Mam HashMap, ale nie wiem jak "zrobić" lub rzucić go jako kolejkę. Dzięki.Czy można utworzyć kolejkę do zestawu HashMap?

Odpowiedz

7

Nie należy używać HashMap bez obsługi bezpieczeństwa wątków kodu. W przeciwnym razie możesz skończyć z Live-lock.

Aby móc iterować mapę w kolejności, w której zostały włożone klucze, można użyć LinkedHashMap.

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

Producent doprowadziłaby wpisy jak ten (nic specjalnego):

m.put(key, object) 

Konsument ankiecie wpisy tak:

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

Dziękuję, że to zadziałało i było szybkie, łatwe i jasne do wdrożenia –

5

Typ LinkedHashMap jest jak kombinacji HashMap i Queue - przechowuje pary klucz/wartość, ale także zapamiętuje kolejność, w jakiej zostały one wstawione. Może to być dokładnie ten typ, którego szukasz. Nie ma wyraźnej funkcji poll(), ale jeśli otrzymasz iterator od LinkedHashMap, odwiedzisz elementy w kolejności, w jakiej zostały dodane. Możesz prawdopodobnie napisać taką funkcję:

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

, która zwróci Ci pierwszy element. Po prostu upewnij się, że synchronizujesz odpowiednio.

Alternatywnie można rozważyć tylko przechowywania pary klucz/wartość wewnątrz Queue definiując klasę pomocniczą Pair a następnie przechowywania Pair S w kolejce.

Mam nadzieję, że to pomoże!

+0

Nicea, więc po prostu trzeba trochę SyncObject do sygnalizować, kiedy możliwe jest odczytanie z LinkedHashMap po stronie konsumenta. –

+0

Witam, LinkedHashMap nie jest bezpieczny dla wątków i nie jest typu Kolejka. – sperumal

+0

@ sperumal- nigdy nie insynuowałem, że jedno z nich miało miejsce. Zakładałem, że PO dostarczy kod synchronizacji. Ponadto, nie uważam, że istnieje jakiekolwiek wymaganie, że musi to być typ 'Queue'; pytanie PO nigdy o tym nie wspomina. Jeśli jest to wymaganie, to takie podejście z pewnością nie zadziała. – templatetypedef

4

Proponuję utworzyć kolejkę EntrySet -

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

Można rozważyć zastosowanie innego rodzaju kolejki, która pozwala umieścić elementy i tylko czeka prdocuer w przypadku non pusty takich jak LinkedBlockingQueue.
W razie potrzeby producent może ponownie skomponować mapę na podstawie obiektów EntrySet.

+0

Hmm, to wygląda na dobrą metodę. Dziękuję, spróbuję. Jedno pytanie, czy ten wątek jest bezpieczny? –

Powiązane problemy