【问题标题】:Is it Possible to create a Queue for HashMap set?是否可以为 HashMap 集创建队列?
【发布时间】:2012-06-21 20:58:36
【问题描述】:

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

【问题讨论】:

    标签: java data-structures collections queue hashmap


    【解决方案1】:

    如果不处理代码的线程安全,则不应使用 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
    }
    

    【讨论】:

    • 谢谢你,这很有魅力,而且实施起来快速、简单、清晰
    【解决方案2】:

    我建议你创建一个EntrySet的队列-

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

    您可以考虑使用另一种类型的队列,它可以让您放置元素,并且只有在LinkedBlockingQueue 等非空的情况下,prdocuer 才会等待。
    然后,如果需要,生产者将能够根据 EntrySet 对象重新组合地图。

    【讨论】:

    • 嗯,这似乎是一个好方法。谢谢你,我会试一试。一个问题是这个线程安全吗?
    • 可能是队列>?
    【解决方案3】:

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

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

    这会给你返回第一个元素。只需确保正确同步即可。

    或者,您可以考虑仅将键/值对存储在 Queue 中,方法是定义一个帮助器类 Pair,然后将 Pairs 存储在队列中。

    希望这会有所帮助!

    【讨论】:

    • 很好,所以他只需要一些 SyncObject 就可以在消费者端从 LinkedHashMap 读取数据时发出信号。
    • 嗨,LinkedHashMap 不是线程安全的,也不是队列类型。
    • @sperumal- 我从来没有暗示过这两种情况都是如此。我假设 OP 会提供同步代码。另外,我不认为它必须是Queue 类型; OP的问题从未提及这一点。如果这是一个要求,那么这种方法肯定行不通。
    • 谢谢,这似乎是一个完美的解决方案,但我还需要做些什么才能使其线程安全?将 volatile 修饰符添加到 LinkedHashMap 就足够了吗?
    • @DavidKroukamp- 有很多方法可以做到这一点,但添加 volatile 不会做到这一点。您需要同步对LinkedHashMap 的访问;可能是通过显式同步,或者可能使用类似Semaphore 的东西。
    猜你喜欢
    • 2019-01-16
    • 2021-05-13
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-02
    相关资源
    最近更新 更多