ConcurrentHashMap上的元素循环法

时间:2013-07-21 06:49:39

标签: java concurrenthashmap thread-synchronization

我正在尝试实现一个在ConcurrentHashMap的元素上执行循环的函数。例如,如果ConcurrentHashMap中有{a,b,c}元素,第一次调用该函数时,它返回a,第二次返回b,第三次返回c,第四次返回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)

2 个答案:

答案 0 :(得分:1)

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

您可能还有一种方法可以在此类中添加和删除对等项。尝试将对等列表和索引保存到该列表中。删除对等方时,从散列映射和对等循环列表中删除该对等方,并相应地更新索引。添加时做同样的事情。

然后,当调用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;
}

答案 1 :(得分:0)

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