1

I have an List of LinkedList objects.

    List<LinkedList<File1>> backup = new ArrayList<LinkedList<File1>>();

The LinkedList contains some elements. I need to add additional elements dynamically by clicking a button. While doing this, I'm getting a concurrent modification error. I really don't understand why this error is popping up. Here is the code:

private void jButton5ActionPerformed(java.awt.event.ActionEvent evt)      
{                                         
    // When JOIN button is clicked
    int parent_node,dist_node;
    // List<File1> temp_list = new ArrayList<File1>();
    File1 f_new = new File1();
    parent_node = Integer.parseInt(jTextField4.getText());
    dist_node = Integer.parseInt(jTextField5.getText());
    LinkedList<File1> tmp_bk = backup.get(parent_node);
    System.out.println("parent node : " + parent_node);
    System.out.println("dist node : " + dist_node);
    System.out.println("no of lists : " + backup.size());
    f_new.nod = backup.size();
    f_new.dist = dist_node;
    // temp_list.add(f_new);
    tmp_bk.add(f_new);

    ListIterator itr = it_bk.get(parent_node);
    while(itr.hasNext())
    {
        File1 f = (File1)itr.next();
        System.out.println("NODE : " + f.nod + "DIST : " + f.dist);
    }

}     
4

3 に答える 3

6

リストを編集していて、元のイテレータを使用しようとしていることが原因である可能性があります。コレクションAPIはそれを許可していません。リストを編集した後、新しいイテレータを作成する必要があります。

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

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

于 2012-04-13T02:55:54.017 に答える
1

まず、人々があなたの質問に注意を向けることを本当に期待している場合は、明確に標準英語で質問することを支持する必要があります。

次に、ConcurrentModificationErrorが発生しているコードの正確な場所を示す必要があります。

最後に、it_bkとは何ですか?説明なしでコードに表示されるだけです。それがListIteratorsのArrayListである場合、そのparent_node番目の要素がhasNext()またはnext()が安全であるかどうかわからない状態にある可能性は確かにあります。tmp_bk.add(f_new);を使用して基になるコレクションを変更したと思います。そのため、既存のイテレータは、その不変条件に違反する可能性があることを心配しています。

一般的なアドバイス:イテレータ(またはそれらのコレクション)を作成して保持しないでください。イテレータが必要な場合は、作成して使用し、破棄します。

于 2012-04-13T03:49:33.963 に答える
0

JDK 1.5 の java.lang.Colletions は同期されません。以前のバージョン (jdk 1.4) では、この問題は発生しません。

これらの問題には複数の解決策があり、ユースケースに応じて賢く選択する必要があります。

  • 解決策 1: list.toArray() を使用してリストを配列に変換し、配列を反復処理することができます。リストが大きい場合、この方法はお勧めできません。

  • 回答 2: コードを同期ブロック内にラップすることにより、反復中にリスト全体をロックできます。このアプローチは、アプリケーションの同時実行が多い場合、アプリケーションのスケーラビリティに悪影響を及ぼします。

  • 回答 3: JDK 1.5 は ConcurrentHashMap および CopyOnWriteArrayList クラスを提供します。これにより、スケーラビリティが大幅に向上し、ConcurrentHashMap.iterator() によって返される反復子は、スレッド セーフを維持しながら ConcurrentModificationException をスローしません。

  • 回答 4: 基になるコレクション「myStr」への参照を持つイテレータ「it」を介して現在のオブジェクトを削除します。Iterator オブジェクトは、この目的のために it.remove() メソッドを提供します。

于 2012-04-13T04:12:58.130 に答える