问题
I have to ensure while iterating the Vector; there is no update on that Vector to avoid ConcurrentModificationException
. I can use concurrent collection. But i just want to give a try on Vector. Below is the code I have written.
public class TestConcurrentModification1 {
Vector a = new Vector();
public static void main(String[] args) {
final TestConcurrentModification1 obj = new TestConcurrentModification1();
new Thread(){
public void run(){
for(int i = 0; i < 5; i++){
try {
Thread.sleep(1);
} catch (InterruptedException e) {}
obj.a.add(""+i);
}
System.out.println(obj.a);
}
}.start();
new Thread(){
public void run(){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
synchronized (obj.a) {
Iterator itr = obj.a.iterator();
while(itr.hasNext()) {
obj.a.add("TEST");//java.lang.OutOfMemoryError: Java heap space
//itr.remove(); //java.lang.IllegalStateException
}
}
}
}.start();
}
}
But the above code is throwing 1) OutOfMemoryError
OR 2) IllegalStateException
. Could you please explain what is causing these two exception. And how to achieve my goal of avoiding ConcurrentModificationException
on a Vector
?
I have to solve this for Java 1.4.2 or prior.
回答1:
One part of your Problem:
Iterator itr = obj.a.iterator();
while(itr.hasNext()) {
obj.a.add("TEST");// <- if itr.hasNext() would have returned false in next iteration, now it won't
}
This is an infinite loop that increases memory usage in each iteration. So you'll run into an OutOfMemory sooner or later.
I suggest using a good old for-loop for inserting values. Use an iterator if you actually want to iterate something :)
More: You are synchronizing against a non-final member.
More: Iterator.remove throws ...
IllegalStateException - if the next method has not yet been called, or the remove method has already been called after the last call to the next method.
And last but not least: The race condition already mentioned by Sotirios (+1 for him). Whenever you synchronize, make sure you synchronize every call on the critical resource.
回答2:
You have a good old race condition on your hands.
Your first Thread
, except for adding the first element to your Vector
, serves absolutely no purpose. You can replace it with
obj.a.add("first");
The beef, as others have noted, is here
Iterator itr = obj.a.iterator();
while (itr.hasNext()) {
obj.a.add("TEST");// java.lang.OutOfMemoryError: Java
// heap space
// itr.remove(); //java.lang.IllegalStateException
}
itr.hasNext()
is implemented as
public boolean hasNext() {
return cursor != elementCount;
}
Where cursor starts at 0
and elementCount
is the size of your Vector
. This call will never return false
. Your while
loop with loop, adding elements, until the program runs out of memory. The cursor
never moves forward because you never call next()
. If you do call next()
while adding elements directly to the Vector
, you will get a ConcurrentModificationException
.
来源:https://stackoverflow.com/questions/19384056/how-to-concurrently-modify-a-vector