关于并发修改异常

时间:2012-08-06 12:49:47

标签: java multithreading

请问是否有任何方法可以在单线程环境中发生并发修改异常,我发布的下面的应用程序包含两个线程,请告诉我在单个线程中也可以看到相同的异常..请指教

package concurrentmodificationError;

import java.util.*;

class ItrDemo
{
    public static void main(String arg[])
    {
       Vector v=new Vector();
       v.addElement("Amit");
       v.add("Rahul");
       v.add(1,"Nitin");
       v.addElement("Ankit");
       System.out.println("There are "+v.size()+"elements in the vector ");

       final Iterator itr=v.iterator();
       Thread th=new Thread()    {
               public void run()
               {
                   System.out.println("New Thread started,traversing     elements of vector...");
                   System.out.println("Contents of vector are...");
                   while(itr.hasNext())
                   {
                     System.out.println(itr.next());
                     try
                      {
                          Thread.sleep(2000);
                       }
                      catch(Exception e1)
                      {
                      }
                   }
              }
         };// end of annomyous class
      System.out.println("Suspending main thread and starting a new thread       for traversing the contents of vector...");
      th.start();
      try
       {
           Thread.sleep(1000);
       }
       catch(Exception e1)
       {
       }
       System.out.println("main thread resumed,modifying vector...");
       v.remove("Ankit");
       v.add("Puneet");
       v.add("Raman");
       System.out.println("Vector Modified , Ankit removed and Puneet &        Raman added.");
  }

}

是的我得到了人们,在单线程环境中,这个错误可能会出现......如下面的代码所示..

System.out.println("Content of list are : ");
          ListIterator itr1=list.listIterator();
          while(itr1.hasNext())
          {
              list.add(new Emp("Anand","Manager",56000)); //
            Emp e=(Emp)itr1.next();  
            e.display();
          }

请告知有什么方法可以克服它..所以没有得到这个错误.. !!请指教

6 个答案:

答案 0 :(得分:2)

参考ConcurrentModificationException的Javadoc,

  

请注意,此异常并不总是表示对象具有   由另一个线程同时修改。如果是单线程   发出一系列违反合同的方法调用   一个对象,该对象可能抛出此异常。例如,如果是   线程在迭代时直接修改集合   使用失败快速迭代器进行集合,迭代器将会发生这种情况   异常。

当线程安全集合受并发访问时,并不总是抛出此异常。任何结构修改(添加/删除)都会提示此异常发生。

在您的特定示例中,您正在修改Iterator之外的集合,因此一旦线程从睡眠状态唤醒,它可能会抛出此异常。

答案 1 :(得分:2)

是的,在单线程环境中也可以获得此异常(而不是错误)。 更准确地说,只要当前正在迭代的集合被另一个线程或当前线程修改,就抛出异常。

您遇到此错误的单线程方案示例如下:

Iterator<String> names = namesList.iterator();
while(names.hasNext()){
    String currentName = names.next();
    if(currentName.startsWith("A")){
           namesList.remove(currentName); //here you modify the original collection
    }
}

在这种情况下,如果迭代器是一个快速失败的迭代器(正如大多数集合实现所提供的那样),你将得到一个ConcurrentModificationException

答案 2 :(得分:1)

如果在迭代时修改了集合,则即使在单个线程中也会抛出

ConcurrentModificationException。 e.g。

        List<String> lst = new ArrayList<String>();
        lst.add("sample");

        for(String str : lst) {
            lst.add("simple");
        }

答案 3 :(得分:0)

单个线程中CME的经典示例类似于

List<String> strs = new ArrayList<String>();
strs.add("foo");
strs.add("bar");

for(String str : strs) {
  strs.add(str + " added");
}

CME会触发,因为您正在迭代列表并且通过迭代器修改。允许 通过其迭代器修改列表而无需获取CME:

ListIterator<String> strIt = strs.listIterator();
while(strIt.hasNext()) {
  String str = strIt.next();
  strIt.add(str + " added");
}
// strs now contains "foo", "foo added", "bar", "bar added"

答案 4 :(得分:0)

可以在单个线程环境中抛出ConcurrentModificationException。只要在不应该​​在不应该在另一个线程中的上下文中修改对象,就会使用它。

示例:

public class CME {
    public static void main(String...args) {
        HashSet<Integer> coll = new HashSet<Integer>();
        coll.add(1);
        coll.add(2);
        coll.add(3);

        for(Integer i : coll) {
            coll.remove(i); // Throws ConcurrentModificationException
        }
    }
}

答案 5 :(得分:0)

你的问题似乎(对我来说)有点神秘......

关于您的第一个问题,在单线程环境中获取ConcurrentModificationException,您需要做的就是这样:

List<String> list =...;
for (String str : list)
{
    list.remove(str); //this should yield the exception
}

关于你的第二个问题,你发布的代码(有两个主题的代码)很可能会出现这样的异常。到目前为止,由于您拥有的物品数量和超时值,它正在运作。如果你改变这些,你很可能会遇到这种例外。

为避免这种情况,您可以使用synchronized blocks。通过允许每个线程进行同步部分,通过它可以进行集合修改,您应该能够避免并发修改异常。

您还可以通过使用Semaphore来管理对列表的访问。