[英]Getting concurrent modification exception while using iterator in multithreaded program
My code is: 我的代码是:
class Processor implements Runnable {
private int id;
private Integer interaction;
private Set<Integer> subset;
private volatile static AtomicBoolean notRemoved = new AtomicBoolean(true);
public Object<E> dcp;
public Iterator<Integer> iterator;
public Processor(int id, Integer interaction, Set<Integer> subset, Object<E> dcp, Iterator<Integer> iterator) {
this.id = id;
this.interaction = interaction;
this.subset= subset;
this.dcp = dcp;
this.iterator = iterator;
}
public void run() {
while (Processor.notRemoved.get()){
System.out.println("Starting: " + this.subset);
if (this.dcp.PA.contains(this.interaction)){
this.subset.add(this.interaction);
this.dcp.increaseScore(this.subset);
if (!this.subset.contains(this.interaction) && Processor.notRemoved.get()){
Processor.notRemoved.set(false);
iterator.remove();
}
}
System.out.println("Completed: " + this.id);
}
}
}
public class ConcurrentApp {
public void multiThreadProgram (Object<E> dcp, int threads) {
ExecutorService executor = Executors.newFixedThreadPool(threads);
int i =1;
while ((dcp.PA.size() > i) && (i <= dcp.R)){
for (Iterator<Integer> iterator = dcp.PA.iterator(); iterator.hasNext();){
Integer interaction = iterator.next();
ArrayList<Integer> removed = new ArrayList<Integer>(dcp.PA);
removed.remove(interaction);
ArrayList<Set<Integer>> subsets = dcp.getSubsets(removed, i);
for (int j = 0; j< subsets.size(); j++){
try {
executor.submit(new Processor(j, interaction, subsets.get(j), dcp, iterator));
} catch (RejectedExecutionException e){
System.out.println("Task was rejected");
}
}
}
System.out.println("All tasks completed");
i++;
}
executor.shutdown();
System.out.println("All tasks submitted");
try {
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I'm getting java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source)... . 我在java.util.ArrayList $ Itr.checkForComodification(Unknown Source)处获取了java.util.ConcurrentModificationException 。
However, I thought that by using the iterator, I could avoid this problem of iterating over my collection while modifying my collection at the same time. 但是,我认为通过使用迭代器,可以避免在修改集合的同时迭代集合的问题。 I didn't have this problem in my non-multithreaded implementation of my program so I'm assuming this has to do with multiple threads doing something with iterator.
我在程序的非多线程实现中没有这个问题,所以我假设这与使用迭代器执行某些操作的多个线程有关。 Does anyone have any ideas?
有人有什么想法吗?
Java's ArrayList isn't thread safe, regardless of whether you use an iterator. Java的ArrayList并不是线程安全的,无论您是否使用迭代器。
If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改列表,则必须在外部进行同步。
... ...
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException
此类的迭代器和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时间以任何方式对列表进行结构修改,则除了通过迭代器自己的remove或add方法之外,迭代器都会抛出ConcurrentModificationException
Take a look at this question for a discussion of thread-safe alternatives. 请看一下这个问题 ,以讨论线程安全替代方案。 Basically, you'll need to either use locks (such as
synchronized
blocks), or a suitable thread-safe list. 基本上,您将需要使用锁(例如
synchronized
块)或适当的线程安全列表。
I thought that by using the iterator, I could avoid this problem of iterating over my collection while modifying my collection at the same time.
我以为通过使用迭代器,可以避免在修改集合的同时迭代集合的问题。
This is true about ListIterator<T>
s, not simply Iterator<T>
s. 关于
ListIterator<T>
,这是正确的,而不仅仅是Iterator<T>
。 In order to avoid ConcurrentModificationException
on removal, several things must be true: 为了避免在删除时发生
ConcurrentModificationException
,必须满足以下几点:
ListIterator<T>
must support remove()
- this operation is optional ListIterator<T>
必须支持remove()
-此操作是可选的 remove()
- removing directly from the list does not work remove()
来删除项目 -直接从列表中删除不起作用 ListIterator<T>
takes care of removals through the same iterator object; ListIterator<T>
负责通过同一迭代器对象进行删除; they do not help when your code removes items concurrently from different threads.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.