我正在尝试实现一个在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)
答案 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()。这是安全的。