5

次の行でエラーが発生します。jsonarrayに追加するプロセスを実行しています。私を助けてください。

jsonArr=new JSONArray();
if(req.getSession().getAttribute("userses")!=null){
    String name=(req.getParameter("name")==null?"":to_EnglishName(req.getParameter("name").toUpperCase()));
    if(!name.equals("")){
        for(Book c:GlobalObjects.bookList){
            if(c.getBookName().startsWith(name)){
                    jsonObjec=new JSONObject();
                    jsonObjec.put("label",c.getBookName());
                    jsonObjec.put("value", c.getId());
                    jsonArr.add(jsonObjec);//java.util.ConcurrentModificationException
            }
        }
    }
}
jsonArr.write(res.getWriter());
4

7 に答える 7

16

これは、再プログラミング中によく発生するエラーです。この例外の理由または詳細はかなり明確です。繰り返されている間、コレクションを変更することは許可されていません(新しい要素を追加しています)。少なくとも構文forはそれをサポートしていません。

あなたの問題を解決するために、私がそれが簡単だと思う2つの方法があります。

1)。ステートメントを使用してループするのではなく、forイテレータを使用してConcurrentModificationExceptionを回避することをお勧めします。

    Iterator<Book> iterator = bookList.iterator();
    while(iterator.hasNext()){
      Book c = iterator.next();
      if(c.getBookName().startsWith(name)){
                jsonObjec=new JSONObject();
                jsonObjec.put("label",c.getBookName());
                jsonObjec.put("value", c.getId());
                jsonArr.add(jsonObjec);
        }
    }

2)。ループしている間は追加しないでください。

     List list = new ArrayList<>();
     for(Book c:GlobalObjects.bookList){
        if(c.getBookName().startsWith(name)){
                jsonObjec=new JSONObject();
                jsonObjec.put("label",c.getBookName());
                jsonObjec.put("value", c.getId());
                list.add(jsonObjec);//java.util.ConcurrentModificationException
        }
     }
     jsonArr.addAll(list);
于 2012-07-10T08:40:28.887 に答える
3

この問題を修正するには、次のことを確認してIf your collection is not thread safe then it must not get modified with another thread when some other thread is iterating over this collectionください。

この問題を解決するには2つの方法があります-

1)1つの解決策は、コレクションへのすべてのアクセスを同期することです

2)次のようなスレッドセーフコレクションを使用しますCopyOnWriteArrayList

JavaDocから-

この例外は、オブジェクトの同時変更が許可されていない場合に、そのような変更を検出したメソッドによってスローされる可能性があります。

たとえば、別のスレッドがコレクションを反復処理しているときに、あるスレッドがコレクションを変更することは一般的に許可されていません。一般に、これらの状況では、反復の結果は定義されていません。一部のIterator実装(JREによって提供されるすべてのコレクション実装の実装を含む)は、この動作が検出された場合にこの例外をスローすることを選択する場合があります。これを行うイテレータは、将来の不確定な時間に任意の非決定的な動作のリスクを冒すのではなく、迅速かつクリーンに失敗するため、フェイルファストイテレータと呼ばれます。

于 2012-07-10T06:29:42.840 に答える
2

コレクションを反復処理し、ループ内で同じコレクションを変更すると、ConcurrentModificationExceptionが発生します。与えられたコードスニペットはそれを示していないので、コレクションを変更する上または下に何か他のものがあります。インスタンス化する場所でjsonArrを宣言してみてください。

考えられる理由の1つは、jsonArrインスタンスオブジェクトがクラスレベルであり、複数のスレッドによってアクセスされていることです。インスタンス化されるjsonArrオブジェクトを宣言します。

編集:jsonArrをローカル変数にします。

于 2012-07-10T06:29:09.340 に答える
1

また、もう1つの方法があります。つまり、実際のリストを渡す代わりに、リストのクローンを繰り返し渡すことができます。

listForIteration = list.clone();

//操作を行います。

于 2015-12-10T07:11:01.660 に答える
0

別のスレッドからjsonArrにアクセスしていますか?つまり、同時に変更するときにjsonArrを反復処理します。

コレクションを反復処理すると同時にコレクションを変更すると、ConcurrentModificationExceptionがスローされます。

于 2012-07-10T06:24:28.910 に答える
0

または、同じリストの反復と変更を可能にするListIteratorを使用します

http://docs.oracle.com/javase/6/docs/api/java/util/ListIterator.html

于 2013-09-25T11:56:51.877 に答える
0

使用するだけjava.util.concurrent.CopyOnWriteArrayList

List<String> empList = new CopyOnWriteArrayList<>();
empList.add("Mojtaba");
empList.add("Mojtabye");
empList.add("Yeganeh");

for (String item : empList) {
    System.out.println(item);
    empList.add("test");
}
于 2016-08-17T13:31:06.120 に答える