Why isn't this code causing a ConcurrentModificationException?
According to the Java API docs Iterator.hasNext does not throw a ConcurrentModificationException
.
After checking "January"
and "February"
you remove one element from the list. Calling it.hasNext()
does not throw a ConcurrentModificationException
but returns false. Thus your code exits cleanly. The last String however is never checked. If you add "April"
to the list you get the Exception as expected.
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String args[]) {
List<String> myList = new ArrayList<String>();
myList.add("January");
myList.add("February");
myList.add("March");
myList.add("April");
Iterator<String> it = myList.iterator();
while(it.hasNext())
{
String item = it.next();
System.out.println("Checking: " + item);
if("February".equals(item))
{
myList.remove(item);
}
}
for (String item : myList)
{
System.out.println(item);
}
}
}
http://ideone.com/VKhHWN
java.util.ConcurrentModificationException not thrown when expected
The iterator returned from ArrayList.iterator()
in the implementation we're apparently both using only checks for structural modification in calls to next()
, not in calls to hasNext()
. The latter just looks like this (under Java 8):
public boolean hasNext() {
return cursor != size;
}
So in your second case, the iterator "knows" that it's returned two elements, and that the list only has two elements... so hasNext()
just returns false, and we never end up calling next()
the third time.
I would view this as an implementation detail - basically the checking not being as strict as it could be. It would be entirely reasonable for hasNext()
to perform a check and throw an exception in this case too.
For java List concurrent modification exception not thrown if remove method invoked before iteration
Look at ArrayList.Itr
.
There're two counters: ArrayList.modCount
and ArrayList.Itr.expectedModCount
. ArrayList.Itr
throws ConcurrentModificationException
when modCount != expectedModCount
.
This is correct. But if you look at ArrayList.Itr.hasNext
you can see:
public boolean hasNext() {
return cursor != size;
}
When you remove one element and you list become empty, then your code does not invoke it.next()
.
To make your code throw ConcurrentModificationException
, you should have not empty list before while loop:
public static void main(String[] args)
{
List<String> l1 = new ArrayList<>();
l1.add("v1");
l1.add("v2");
Iterator<String> it = l1.iterator();
l1.remove(0);
while(it.hasNext()) {
System.out.println(it.next()); // --> ConcurrentModificationException
}
}
Why does this code cause a ConcurrentModificationException in Java?
I'm assuming you're rendering something to screen in the code.frame.GameEngine.render()
method. The problem is you're using a LinkedList
which is not thread-safe. Thus, it's possible to add a new GUIElement
to elements
while code.frame.GameEngine.render()
method is iterating over elements
(this happens asynchronously). You need to use a thread-safe collection like:
List<GUIElement> elements = Collections.synchronizedList(new LinkedList<GUIElement>());
Java ConcurrentModificationException
I'm seeing the same thing,
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Launcher
{
public static void main(String[] args)
{
doThis();
doThat();
}
private static void doThis()
{
System.out.println("dothis");
try
{
List<String> myList1 = new ArrayList<String>();
Collections.addAll(myList1, "str1","str2","str3","str4","str5");
for(String element : myList1){//no ConcurrentModificationException here
if(element.equalsIgnoreCase("str4"))
myList1.remove("str4");
}
System.out.println(myList1);
}
catch(Exception e)
{
e.printStackTrace();
}
}
private static void doThat()
{
System.out.println("dothat");
try
{
List<String> myList2 = new ArrayList<String>();
Collections.addAll(myList2, "str1","str2","str3","str4","str5");
for(String element : myList2){//ConcurrentModificationException here
if(element.equalsIgnoreCase("str1"))
myList2.remove("str1");
}
System.out.println(myList2);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
which outputs,
dothis
[str1, str2, str3, str5]
dothat
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at com.foo.Launcher.doThat(Launcher.java:41)
at com.foo.Launcher.main(Launcher.java:12)
And I've found the reason.
ConcurrentModificationException: Why does removing the null in List throw this Exception if it´s not the first variable
Well, in a best case scenario, the ConcurrentModificationException
should be thrown in any of the two cases. But it isn't (see the quote from the docs below).
If you use the for-each loop to iterate over an Iterable
, the Iterator
returned by the iterator()
method of the data structure will be used internally (the for-each loop is just syntactic sugar).
Now you shouldn't (structurally) modify an Iterable
that is being iterated after this Iterator
instance was created (it's illegal unless you use the Iterator
's remove()
method). This is what a concurrent modification is: There are two different perspectives on the same data structure. If it's modified from one perspective (list.remove(object)
), the other perspective (the Iterator) won't be aware of this.
It is not about the element being null
. The same happens if you change the code to remove the string:
ArrayList<Object> s = new ArrayList<>();
s.add("test");
s.add(null);
try {
System.out.println(s + "\n");
for (Object t : s) {
System.out.println(t);
if (t != null && t.equals("test")) {
s.remove(t);
System.out.println("ObjectRemoved = " + t + "\n");
}
}
System.out.println(s + "\n");
} catch (ConcurrentModificationException e) {
System.out.println(e);
} catch (Exception e) {
System.out.println(e);
}
Now the reason this behaviour differs in some scenarios is simply the following (from the Java SE 11 Docs for 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. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.
Getting concurrent modification exception while using iterator in multithreaded program
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.
Related Topics
How I Save and Retrieve an Image on My Server in a Java Webapp
Stopping a Window from Displaying Till It Is Fully Drawn
What Is the Best/Simplest Way to Read in an Xml File in Java Application
How to Copy File Inside Jar to Outside the Jar
Checking for Null - What Order
Stringutils.Isblank() VS String.Isempty()
How to Do If-Else in Thymeleaf
Filter Java Stream to 1 and Only 1 Element
Resultset.Getstring(1) Throws Java.Sql.Sqlexception: Invalid Operation at Current Cursor Position
Fast Algorithm for Searching for Substrings in a String
Output an Image File from a Servlet
Does Java Support Inner/Local/Sub Methods
Performance Difference Between a Wild Card Import and the Required Class Import