Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top