How to concurrently modify a Vector

若如初见. 提交于 2019-12-11 19:28:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!