11

现在我正在尝试创建一个生产者/消费者线程,生产者线程遍历所有可能的字母组合并创建它们各自的 MD5 哈希值。然后将每个组合及其哈希放入HashMap<String,String>. 现在在我的消费者线程中,我希望能够使用Queue<>哈希图上的集合,以便我的消费者线程可以调用poll()etc 从而像 a 一样删除值 atcQueue但仍然让我能够在调用时看到组合及其哈希我该poll()怎么办关于这样做?我有HashMap但不知道如何“制作”或将其转换为队列。谢谢。

4

3 回答 3

12

如果不处理代码的线程安全,则不应使用 HashMap。否则,您可能会以 Live-lock 结束。

为了能够按照插入键的顺序迭代您的 Map,您可以使用 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
}
于 2012-06-19T19:16:06.783 回答
10

LinkedHashMap类型就像 aHashMap和 a的组合Queue——它存储键/值对,但也记住它们的插入顺序。这可能正是您正在寻找的类型。没有明确的poll()函数,但如果你得到一个迭代器,LinkedHashMap你将按照它们被添加的顺序访问元素。然后你可能会写一个这样的函数:

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

这将使您返回第一个元素。只要确保适当地同步即可。

或者,您可以考虑Queue通过定义一个帮助类Pair然后将Pairs 存储在队列中来将键/值对存储在 a 中。

希望这可以帮助!

于 2012-06-19T18:53:24.287 回答
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 对象重新组合地图。

于 2012-06-19T18:58:40.163 回答