我们有一个采用经典生产者/消费者方法的多线程应用程序,该方法使用ConcurrentHashmap队列。
使用者启动一个线程,该线程内部具有无限循环,并发散列图上的另一个嵌套循环可读取并删除每个已处理的项目。
我要问自己该代码相对于地图上的“ for”迭代和每个元素“删除”是否安全/高效。
运行代码似乎是正确的...
new Thread(t.getContextName()+"-RespMsgThread") {
public void run() {
try {
do {
for (Entry<Integer, AbstractMessage> nodeEntry : t.getHtForResponse().entrySet())
{
--> Doing some stuff with the node Entry
// remove the node from the queue
t.getHtForResponse().remove(nodeEntry.getKey());
}
yield();
}
while (!t.isStopControllerRun());
} catch (InterruptedException ex) {
Context.getInstance().getLogger().info("ERROR: " + ExceptionUtils.getStackTrace(ex));
}
}
}.start();
答案 0 :(得分:3)
是的,它对于“ for”迭代完全安全/有效。有一个陷阱,因为ConcurrentHashMap的迭代器是弱一致性的,因此您可以删除未处理的键的值(在这种情况下,使用节点Entry做一些事情)。
因此您可以考虑调用方法
remove(Object key, Object value)
removes the entry for a key only if currently mapped to a given value.
代替普通的删除(对象键)方法
答案 1 :(得分:1)
如果地图上没有物品,您只能屈服,也许您可以睡觉。除了睡眠以外,您可以使用类似BlockingQueue的方法。通过在BlockingQueue上使用take()方法,您将在插入项目后立即获得它。 您还可以使用poll(timeout, timeunit)方法检查线程是否已停止。