Exception in thread "Thread-7" java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449) at java.util.AbstractList$Itr.next(AbstractList.java:420) at Main.CGuiUpdater.run(CGuiUpdater.java:139) at java.lang.Thread.run(Thread.java:595)
It's a static List. Several threads poll this list to get some information but no modification. Whenever runing to CGuiUpdater.run, the runtime exception throws. Is it because I use Iterator to iterator List or something else? And how to resolve it, Thanks.
It's a combination of things - it's because you're using the Iterator at the same time another thread is modifying the list, and there's apparently no synchronization (or perhaps, insufficient or incorrect synchronization) to prevent these events from occurring near-simultaneously.
One solution is to synchronize all access to the List, using the list itself as the monitor:
Whatever other threads are modifying the list, they need to be synchronized too, also on the list. E.g.:
or
Now this may be undesirable if the list is long and performance is critical, because if it takes a long time to iterate through the list, other threads are also blocked while waiting for this to complete. There are various alternatives. One is to use a CopyOnWriteArrayList. This is good if writes are fairly infrequent. You may also be able to revise your code in a way that it is not necessary to iterate an entire list. You may be able to use other data structures instead, such as ConcurrentHashMap or ConcurrentLinkedQueue. It's hard to say what would be most suitable here without more details on what you're doing.
The list is modified(add elements)only at the begining. The following code only get elements from it. So I'm thinking if I can make sure the modification operation occurs before getting operation, the exception won't happen?
Yes, that should be correct. If you're seeing this exception, then probably one thread is not done initializing the list before another thread checks it. Even if common sense is telling you it really should be done. Threads can do some strange things.
One approach is something like this:
Note that when you initialize the list, no other thread can possibly know about it yet. "list" is just a local variable, while "myList" does not yet know anything about the new list. Only after it's initialized does myList get the reference to the list. The fact that myList is declared final here is actually important for subtle reasons - otherwise the compiler or JIT may perform some weird optimizations that you only notice when multiple threads are involved. And then only rarely - but when they happen, they're a real pain to track down.
If making the variable final is not an option for you, there are other strategies. Maybe make it volatile - but then you have to worry about whether it's null, before you do anything with it. As it is now (with final), that's not possible.
For more extended discussion of this and many related threading issues, I heartily recommend Java Concurrency in Practice, an excellent use of time and money for any multithreaded programmer (at least if they're already pretty comfortable with the threading topics covered in the Java Tutorial). [ August 29, 2007: Message edited by: Jim Yingst ]
I have a method which retrieves a java.util.List of objects for display on the UI and this method is always access concurrently by hundred or even thousands of threads at the same time(high concurrency),
however if certain condition is true I need to remove some objects from that List before it is returned by that method, since this method has a very high usage I must take performance into account therefore
I can't use synchronized block in the method, I just want some confirmations I can't use Iterator.remove in a multi-thread situation but there should be no performance difference in directly looping through the
list using
(for int i=0; i<List.size(); i++) {List.get(i)}
and with
for (final Iterator i = temp.iterator(); i.hasNext();) ,
I have attached the following code snippets
I want to confirm here in a multithreaded situation the i.remove() would not work in the above method?
my currently solution is as follows and would like to know if are there any advises to better improve this method for better efficiency since it is a critical method
I know this is an old topic but a simple, elegant solution is as follows:
Since Java does shallow copying on clone() calls this seems to work fine and since they (original & clone) have different iterators there's no violation when the original is modified.
Note that fail-fast behavior cannot be guaranteed [snip]. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness
So, yeah, on the 2nd to last iteration, Java may not do you the favor of telling you that you have a bug.
I had a similar problem with one of the method variables. Spent hours debugging . Finally had to use Collections.unmodifiableList to
retrieve a unmodifiable list.
Feel it has more to do with the JRE being used.
Dennis Hopper wrote:I know this is an old topic but a simple, elegant solution is as follows:
Since Java does shallow copying on clone() calls this seems to work fine and since they (original & clone) have different iterators there's no violation when the original is modified.
Not sure what the point of that is supposed to be.
First, it runs in O(n^2).
Second, it accomplishes nothing more than list.clear().
I had a similar problem with one of the method variables. Spent hours debugging . Finally had to use Collections.unmodifiableList to
retrieve a unmodifiable list.
Feel it has more to do with the JRE being used.
Sorry, I'm confused. What problem exactly did you have? And how did using unmodifiableList() solve it? And why do you think it's a JRE-specific issue?
Since evidently it requires explanation I will explain. This isn't necessarily slower than a normal for-loop; just make the clone call and save it to a variable.
And this code's applicability is not limited to clearing an array. Using this technique one can use all the functions of the List class and without the liability of having to use the ugly Iterator interface. And since you aren't modifying the original you don't need to worry about throwing ConcurrentModificationException instances. This should be pretty obviously the correct solution for this problem.
Since evidently it requires explanation I will explain. This isn't necessarily slower than a normal for-loop;
It may not necessarily be slower than a poorly written for loop, but it's definitely slower than a normal one.. As I said previously: It's O(n^2) and it accomplishes only list.clear(), which is O(1).
just make the clone call and save it to a variable.
That's identical to the original. Introducing the variable changes nothing.
And this code's applicability is not limited to clearing an array. Using this technique one can use all the functions of the List class and without the liability of having to use the ugly Iterator interface.
It's nonstandard, confusing code that serves no purpose. Iterator isn't particularly ugly. There are cases where it makes sense to operate on a copy of the original, but there's nothing about your example that makes any sense.
And since you aren't modifying the original
In the example you gave you certianly are. You're clearing it the very, very long way around.
you don't need to worry about throwing ConcurrentModificationException instances. This should be pretty obviously the correct solution for this problem.
There are already better and easy-to-use approaches to avoiding CME. Whatever the original problem was, I guarantee this is not even remotely a correct solution.
Post by:autobot
Morning came much too soon and it brought along a friend named Margarita Hangover, and a tiny ad.
a bit of art, as a gift, that will fit in a stocking