简体   繁体   English

ConcurrentHashMap上的元素轮循

[英]element round robin on ConcurrentHashMap

I am trying to implement a function that do a round robin on elements of a ConcurrentHashMap. 我正在尝试实现对ConcurrentHashMap的元素进行轮循的功能。 For example, if there are {a, b, c} elements in the ConcurrentHashMap, the first time I call the function, it returns a, the second time, it returns b, the third time, it returns c, the forth time, it returns a. 例如,如果ConcurrentHashMap中有{a,b,c}个元素,那么我第一次调用该函数时,它将返回a,第二次,它将返回b,第三次,它将返回c,第四次,它返回一个。

private static Enumeration<Peer> nhEnmu;
private static final ConcurrentHashMap<String, Peer> peers;

private synchronized static Peer getNextPeer()
{
    if (nhEnmu == null || !nhEnmu.hasMoreElements())
    {
        nhEnmu = peers.elements();
    }

    return nhEnmu.nextElement();
}

I implemented this function as above, however, the NoSuchElementException keeps poping out, I am wondering that is there anything wrong for using the elements() method? 我如上所述实现了此功能,但是NoSuchElementException不断弹出,我想知道使用elements()方法有什么问题吗? If it is not appropriate, what implementation should I adapt? 如果不合适,我应该采用哪种实现方式? Thank you! 谢谢!

The exception trace is as follows: 异常跟踪如下:

at Main$MsgProcessorThread.run(Main.java:119)
Exception in thread "Thread-1" java.util.NoSuchElementException at
java.util.concurrent.ConcurrentHashMap$HashIterator.nextEntry(ConcurrentHashMap.java:1266) at
java.util.concurrent.ConcurrentHashMap$ValueIterator.nextElement(ConcurrentHashMap.java:1297) at 
control.Protocol.getNextPeer(Protocol.java:89)

According to this question iterators returned are not thread safe. 根据这个问题,返回的迭代器不是线程安全的。 If so, and you are accessing the iterator on multiple thread, this exception could occur. 如果是这样,并且您正在多个线程上访问迭代器,则可能发生此异常。

You probably have a method to add and remove peers in this class too. 您可能也有一种在此类中添加和删除对等项的方法。 Try keeping a list of peers and an index into that list. 尝试保留对等方列表以及该列表中的索引。 When you remove a peer, remove that peer from both the hashmap and your peer round robin list, and update your index appropriately. 当您删除一个对等方时,请同时从哈希图和对等方循环列表中删除该对等方,并适当地更新索引。 Do the same thing when adding. 添加时执行相同的操作。

Then when getNextPeer is called, return the next peer in your list and increment your index. 然后,当getNextPeer时,返回列表中的下一个同级并增加索引。 Wrap back to zero if index exceeds the size of the list. 如果索引超过列表的大小,则换回零。

Something like.... 就像是....

private static List<Peer> nhEnmu;
private static int index;
private static final ConcurrentHashMap<String, Peer> peers;

private synchronized static Peer getNextPeer()
{
    Peer peer = null;
    if (nhEnmu.size()>0)
    {
        peer = nhEnmu.get(index);
        index++;
        if(index>=nhEnmu.size())
            index = 0;
    }
    return peer;
}

Use ConcurrentHashMap.entrySet() directly instead. 直接使用ConcurrentHashMap.entrySet()。 it is safe. 很安全

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM