在并发java应用中使用迭代器for循环 [英] Using iterator over for-loop in concurrent java app

查看:830
本文介绍了在并发java应用中使用迭代器for循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class Nodes 具有 getNodes()方法,未同步。但 List< Node>节点 - 已同步。许多线程可以连接到它,改变节点



像这样:

  class Nodes {
List< Node> nodes = Collections.synchronizedList(new ArrayList< Node>());

public List< Nodes> getNodes(){return nodes; }
...
}

客户代码:

 节点节点; 

synchronized(nodes){

for(Node node:nodes.getNodes()){
...
}

}



我没有询问测试,但是:



我应该使用 while(iterator.hasNext()){var = iterator.next()} 而不是for- p>

因为我知道当我尝试删除 nodes.remove(node)里面for-loop它失败与 ConcurentModificationException






EDIT:



如果迭代器是好用的东西,那么有这个代码(客户端代码):

  Iterator< Node> iter = nodes.getNodes()。iterator(); 
while(iter.hasNext()){// line 1
Node node = iter.next(); // line 2
}

这并不安全:

  1. thread1转到第1行,希望现在iter会返回next()值。 
2.但是在那个时刻thread2删除那个值。
3. thread1有异常并失败。

这是否意味着我应该在客户端上锁定。这是我不想做的。



我有一个解决方案:

  while(iter.hasNext()){

try {
Node node = iter.next();
...

} catch(NoSuchElementException ex){continue;} //处理异常 - do more try
}






编辑



我的案例的答案是:使用 CopyOnWriteArrayList 。我甚至可以留下 for-loop



但另一个选项:只返回客户端列表让他们知道他们想要什么。因为它是一种奇怪的(不一致的)同时提供'快照迭代器'和实时数据在列表中。

解决方案

你应该使用像你建议的迭代器,而不是做一个 nodes.delete()(这真的是一个 nodes.remove 。)),您应该改为 iterator.remove()



你的问题。这是一个更新的答案解决迭代器的原子性。如果你希望你的迭代器在创建它的时候有一个'snapshot'的值,那么你可以使用java.util.concurrent中的并发集合集合,例如 CopyOnWriteArrayList


class Nodes has getNodes() method, which is not synchronized. But List<Node> nodes - is synchronized. Many threads could be connected to it, changing nodes in it.

Like this:

class Nodes {
 List<Node> nodes = Collections.synchronizedList(new ArrayList<Node>() );

 public List<Nodes> getNodes() { return nodes; }
 ...
}

Client code:

Nodes nodes;

synchronized(nodes) {

 for(Node node: nodes.getNodes()) {
  ...
 }

}

I do not have interrogation tests for that, but:

Should I use while(iterator.hasNext()) { var = iterator.next() } instead of for-loop ?

Because I know that when I try to delete nodes.remove(node) inside for-loop it fails with ConcurentModificationException.


EDIT: (related issue)

If iterator is good stuff to use, then having this code (client code):

Iterator<Node> iter = nodes.getNodes().iterator();
while (iter.hasNext()) {  // line 1
    Node node = iter.next();  // line 2
}

It is not safe anyway:

 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.

Does it mean that I should do locking on client side anyway. This is what I don't want to do.

One of the solutions I have:

while (iter.hasNext()) {

    try {
       Node node = iter.next();
       ...

    } catch (NoSuchElementException ex) {continue;}  // handle exception - do more try
}


EDIT:

Answer for my case was: to use CopyOnWriteArrayList. I can even stay with for-loop with it.

But another option: Just return client a copy of the list to let them know whatever they want with it. Because it is kind of strange (inconsistent) providing 'snapshot iterator' AND real data in the list at the same time.

解决方案

You should use an iterator like you have suggest, but instead of doing a nodes.delete() (which is really a nodes.remove(...) ) you should instead do iterator.remove()

You have updated your question. Here's an updated answer addressing the 'atomicity' of the iterator. If you want your iterator to have a 'snapshot' of the values at the time it (the iterator) was created, then you can use the Concurrent set of collections in java.util.concurrent: like CopyOnWriteArrayList

这篇关于在并发java应用中使用迭代器for循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆