1

我正在尝试实现一个对 ConcurrentHashMap 的元素进行循环的函数。比如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();
}

我如上所述实现了这个功能,但是,NoSuchElementException 不断弹出,我想知道使用 elements() 方法有什么问题吗?如果不合适,我应该适应什么实现?谢谢!

异常跟踪如下:

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)
4

2 回答 2

1

根据这个问题,返回的迭代器不是线程安全的。如果是这样,并且您正在多个线程上访问迭代器,则可能会发生此异常。

您可能也有一种方法可以在此类中添加和删除对等点。尝试保留对等点列表和该列表的索引。当你删除一个对等点时,从哈希图和你的对等循环列表中删除那个对等点,并适当地更新你的索引。添加时做同样的事情。

然后当getNextPeer被调用时,返回列表中的下一个对等点并增加索引。如果索引超过列表的大小,则回零。

就像是....

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;
}
于 2013-07-21T07:02:00.737 回答
0

直接使用 ConcurrentHashMap.entrySet() 代替。这是安全的。

于 2013-07-21T07:09:32.520 回答