class Nodes
有getNodes()
方法,即not synchronized
. 但是List<Node> nodes
—— is synchronized
。许多线程可以连接到它,并在其中发生变化nodes
。
像这样:
class Nodes {
List<Node> nodes = Collections.synchronizedList(new ArrayList<Node>() );
public List<Nodes> getNodes() { return nodes; }
...
}
客户端代码:
Nodes nodes;
synchronized(nodes) {
for(Node node: nodes.getNodes()) {
...
}
}
我没有对此进行审讯测试,但是:
我应该使用while(iterator.hasNext()) { var = iterator.next() }
而不是 for-loop 吗?
因为我知道当我尝试nodes.remove(node)
在 for 循环中删除时,它会以ConcurentModificationException
.
编辑:(相关问题)
如果迭代器是好东西,那么有这个代码(客户端代码):
Iterator<Node> iter = nodes.getNodes().iterator();
while (iter.hasNext()) { // line 1
Node node = iter.next(); // line 2
}
反正也不安全:
1. thread1 goes to line 1, hoping that now iter would return him next() value.
2. but at that moment thread2 delete that value.
3. thread1 has Exception and fails.
这是否意味着无论如何我都应该在客户端进行锁定。这是我不想做的。
我拥有的解决方案之一:
while (iter.hasNext()) {
try {
Node node = iter.next();
...
} catch (NoSuchElementException ex) {continue;} // handle exception - do more try
}
编辑:
我的情况的答案是:使用CopyOnWriteArrayList。我什至可以for-loop
和它在一起。
但另一种选择:只需向客户返回一份列表副本,让他们知道他们想要什么。因为同时在列表中提供“快照迭代器”和真实数据有点奇怪(不一致)。