0

シングルスレッド環境で同時変更例外が発生する可能性がある方法と、私が投稿している以下のアプリケーションが2つのスレッドで構成されている方法があることを教えてください。シングルスレッドでも同じ例外を見ることができます..お願いします助言する

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

はい、シングルスレッド環境でもこの例外(エラーではない)が発生する可能性があります。より正確には、現在反復処理しているコレクションが別のスレッドまたは現在のスレッドによって変更されるたびに、例外がスローされます。

このエラーが発生するシングルスレッドシナリオの例は次のとおりです。

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 に答える
2

ConcurrentModificationExceptionの Javadoc を参照すると、

この例外は、オブジェクトが別のスレッドによって同時に変更されたことを常に示すわけではないことに注意してください。1 つのスレッドが、オブジェクトのコントラクトに違反する一連のメソッド呼び出しを発行すると、オブジェクトはこの例外をスローする可能性があります。たとえば、フェイルファスト反復子を使用してコレクションを反復処理しているときに、スレッドがコレクションを直接変更すると、反復子はこの例外をスローします。

スレッドセーフなコレクションが同時アクセスの対象である場合、この例外が常にスローされるとは限りません。構造的な変更(追加/削除) を行うと、この例外が発生します。

特定の例では、 Iterator の外部でコレクションを変更しているため、スレッドがスリープから復帰すると、この例外がスローされる可能性があります。

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

あなたの質問は(私には)少し不可解に思えます...

あなたの最初の質問に関してConcurrentModificationException、シングルスレッド環境で取得するためにあなたがする必要があるのは次のようなものです:

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

2番目の質問に関しては、投稿したコード(2つのスレッドを持つコード)は、このような例外が発生する可能性が最も高くなります。これまでのところ、アイテムの量とタイムアウト値のために機能しています。これらを変更すると、おそらくこの例外が発生します。

これを回避するには、を使用できますsynchronized blocks。各スレッドがコレクションの変更を行うことができる同期セクションを許可することにより、同時変更の例外を回避できるはずです。

を使用して、リストへのアクセスを規制することもできますSemaphore

于 2012-08-06T12:59:06.263 に答える
0

ConcurrentModificationExceptionシングルスレッド環境でAをスローできます。これは、オブジェクトが変更されるべきではないコンテキストで変更されるたびに使用されます。必ずしも別のスレッドで変更される必要はありません。

例:

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

シングル スレッドでの CME の典型的な例は、次のようなものです。

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

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

リストを繰り返し処理していて、 iterator 以外でリストを変更したため、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"
于 2012-08-06T12:57:02.850 に答える