2012-06-19 15 views
9

Momentan versuche ich einen Producer/Consumer Thread zu erstellen, der Producer Thread durchläuft alle möglichen Buchstabenkombinationen und erzeugt die entsprechenden MD5 Hashes. Dann wird jede Kombination und ihr Hash in die HashMap<String,String> eingegeben. Jetzt in meinem Consumer-Thread möchte ich in der Lage sein, die Queue<> Sammlung auf der Hashmap zu verwenden, so dass mein Consumer-Thread poll() etc aufrufen kann, wodurch Werte wie ein Queue wie ein Queue entfernen, aber immer noch mir die Fähigkeit zu sehen, sowohl die Kombination und seine Hash beim Aufruf Wie würde ich das machen? Ich habe die HashMap aber weiß nicht, wie man es als eine Warteschlange "macht" oder es wirft. Danke.Ist es möglich, eine Warteschlange für HashMap-Set zu erstellen?

Antwort

7

Sie sollten keine HashMap verwenden, ohne die Thread-Sicherheit Ihres Codes zu behandeln. Andernfalls können Sie mit einer Live-Sperre enden.

Um die Map in der Reihenfolge durchlaufen zu können, in der die Schlüssel eingefügt wurden, können Sie eine LinkedHashMap verwenden.

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

Der Hersteller würde Einträge wie diese (nichts Besonderes) drücken: zu

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

Vielen Dank das hat einen Charme und war schnell, einfach und klar zu implementieren –

5

Die LinkedHashMap Typ ist wie eine Kombination aus einem HashMap und einem Queue - it Schlüssel/Wert-Paaren speichert, sondern merkt sich auch die Reihenfolge, in der sie eingelegt wurden. Dies könnte genau der Typ sein, nach dem Sie suchen. Es gibt keine explizite poll() Funktion, aber wenn Sie einen Iterator über die bekommen, werden Sie die Elemente in der Reihenfolge, in der sie hinzugefügt wurden, besuchen. Sie könnten dann wahrscheinlich eine Funktion wie diese schreiben:

, die Ihnen das erste Element zurückgeben wird. Stellen Sie nur sicher, dass Sie entsprechend synchronisieren.

Alternativ könnten Sie auch nur Schlüssel/Wert-Paare in einem Queue speichern, indem Sie eine Hilfsklasse Pair definieren und dann Pair s in der Warteschlange speichern.

Hoffe, das hilft!

+0

Nizza, so wird er brauchen nur etwas SyncObject:

m.put(key, object) 

Der Verbraucher Einträge wie diese Umfrage würde signalisieren, wenn es möglich ist, von LinkedHashMap auf der Verbraucherseite zu lesen. –

+0

Hallo, LinkedHashMap ist nicht Thread-sicher und es ist nicht vom Typ Warteschlange. – sperumal

+0

@ sperumal- Ich habe nie angedeutet, dass einer dieser Fälle der Fall war. Ich nahm an, dass das OP den Synchronisationscode liefern würde. Ich glaube auch nicht, dass es eine Anforderung vom Typ "Warteschlange" geben muss; Die Frage des OP erwähnt dies nie. Wenn dies eine Voraussetzung ist, wird dieser Ansatz definitiv nicht funktionieren. – templatetypedef

4

Ich schlage vor, Sie eine Warteschlange von entrySet erstellen -

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

Sie betrachten können, eine andere Art von Warteschlange verwenden, mit dem Sie die Elemente setzen können, und nur die prdocuer wartet bei nicht leer wie LinkedBlockingQueue.
Der Producer kann dann bei Bedarf eine Karte basierend auf den EntrySet-Objekten neu zusammenstellen.

+0

Hmm das scheint eine gute Methode zu sein. Danke, ich werde es versuchen. Eine Frage, das ist dieser Thread sicher? –

Verwandte Themen