0

您能否告诉我在单线程环境中是否可能发生并发修改异常以及我发布的以下应用程序由两个线程组成,请告诉我我能否在单个线程中也看到相同的异常......请建议

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();
          }

请告知有什么方法可以克服它..这样就不会出现此错误..!!请告知

4

6 回答 6

2

参考ConcurrentModificationException的Javadoc ,

请注意,此异常并不总是表示对象已被不同的线程同时修改。如果单个线程发出一系列违反对象约定的方法调用,则该对象可能会抛出此异常。例如,如果线程在使用快速失败迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。

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

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

于 2012-08-06T12:57:07.777 回答
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

于 2012-08-06T12:59:10.530 回答
1

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

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

        for(String str : lst) {
            lst.add("simple");
        }
于 2012-08-06T12:54:54.707 回答
0

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

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

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

CME 触发是因为您正在迭代列表并且您修改它而不是通过 iterator。您可以通过其迭代器修改列表,而无需获得 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"
于 2012-08-06T12:57:02.850 回答
0

AConcurrentModificationException可以在单线程环境中抛出。每当在不应该修改对象的上下文中修改对象时使用它,不一定在另一个线程中。

例子:

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
        }
    }
}
于 2012-08-06T12:58:34.987 回答
0

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

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

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

至于您的第二个问题,您发布的代码(具有 2 个线程的代码)很可能容易出现这种异常。到目前为止,由于您拥有的物品数量以及超时值,它正在工作。如果您更改这些,您很可能会遇到此异常。

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

您还可以通过使用Semaphore.

于 2012-08-06T12:59:06.263 回答