Note that there are some explanatory texts on larger screens.

plurals
  1. POYet another ConcurrentModificationException question
    primarykey
    data
    text
    <p>I am currently trying to learn how to properly handle multi-threaded access to Collections, so I wrote the following Java application.</p> <p>As you can see, I create a synchronized ArrayList which I try to access once from within a Thread and once without.</p> <p>I iterate over the ArrayList using a for loop. In order to prevent multiple access on the List at the same time, I wrapped the loop into a synchronized block.</p> <pre><code>public class ThreadTest { Collection&lt;Integer&gt; data = Collections.synchronizedList(new ArrayList&lt;Integer&gt;()); final int MAX = 999; /** * Default constructor */ public ThreadTest() { initData(); startThread(); startCollectionWork(); } private int getRandom() { Random randomGenerator = new Random(); return randomGenerator.nextInt(100); } private void initData() { for (int i = 0; i &lt; MAX; i++) { data.add(getRandom()); } } private void startCollectionWork() { System.out.println("\nStarting to work on data outside of thread"); synchronized (data) { System.out.println("\nEntered synchronized block outside of thread"); for (int value : data) { // ConcurrentModificationException here! if (value % 5 == 1) { System.out.println(value); data.remove(value); data.add(value + 1); } else { System.out.println("value % 5 = " + value % 5); } } } System.out.println("Done working on data outside of thread"); } private void startThread() { Thread thread = new Thread() { @Override public void run() { System.out.println("\nStarting to work on data in a new thread"); synchronized (data) { System.out.println("\nEntered synchronized block in thread"); for (int value : data) { // ConcurrentModificationException if (value % 5 == 1) { System.out.println(value); data.remove(value); data.add(value + 1); } else { System.out.println("value % 5 = " + value % 5); } } } System.out.println("Done working on data in a new thread"); } }; thread.start(); } } </code></pre> <p>But everytime one of the for loops gets entered, I get a ConcurrentModificationException. This is my console output (which changes with every new run):</p> <pre><code>Starting to work on data outside of thread Entered synchronized block outside of thread 51 Starting to work on data in a new thread Entered synchronized block in thread value % 5 = 2 value % 5 = 2 value % 5 = 4 value % 5 = 3 value % 5 = 2 value % 5 = 2 value % 5 = 0 21 Exception in thread "main" java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372) at java.util.AbstractList$Itr.next(AbstractList.java:343) at ThreadTest.startCollectionWork(ThreadTest.java:50) at ThreadTest.&lt;init&gt;(ThreadTest.java:32) at MultiThreadingTest.main(MultiThreadingTest.java:18) Exception in thread "Thread-1" java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372) at java.util.AbstractList$Itr.next(AbstractList.java:343) at ThreadTest$1.run(ThreadTest.java:70) </code></pre> <p>What's wrong?</p> <p>Ps: Please don't just post links to multi-threaded how-to's since I've already read enough about that. I am just curious why my application doesn't run as I want it to.</p> <hr> <p><strong>Update:</strong> I replaced the for(x : y) syntax with an explicit Iterator and a while loop. The problem remains though..</p> <pre><code>synchronized(data){ Iterator&lt;Integer&gt; i = data.iterator(); while (i.hasNext()) { int value = i.next(); // ConcurrentModificationException here! if (value % 5 == 1) { System.out.println(value); i.remove(); data.add(value + 1); } else { System.out.println("value % 5 = " + value % 5); } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload