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)....
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.
From the Javadoc:
If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
...
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
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.