1

doInBackGround() の Asynctask から呼び出している静的メソッドがあります。

メソッドには、コードの次の部分があります。

    ArrayList<Message> messagesList = new ArrayList<Message>();
    if (!clearList) {
        messagesList.addAll(messages.getMessagesList());
            for (Message msg : messagesList) {
                if (msg.getId().length() == 0) {
                    messagesList.remove(msg);
                }
        }
    }

「同時変更例外」がスローされることがあります。メソッドを「同期済み」として宣言しようとしましたが、それでも役に立ちませんでした。ブロックを同期済みと宣言できません。これは静的メソッドであり、「this」参照がないためです。 .

別の asynctask を開始する必要がある場合は、実行中の asynctask を停止しようとしましたが、同様に役に立ちませんでした。

助けていただければ幸いです。

4

6 に答える 6

5

これは同期とは関係ありません。イテレータを使用してループしていますが、反復中に変更するためにmessagesList使用しています。反復中にリストが変更されると、 の反復子が失敗するremoveため、これはできません。ドキュメントArrayListから:

このクラスのiteratorおよびlistIteratorメソッドによって返される反復子は、フェイルファストですremove。反復子の作成後に、反復子自体のまたはメソッド以外の方法でリストが構造的に変更された場合add、反復子は をスローしConcurrentModificationExceptionます。

強化されたforループは、 を使用したシンタックス シュガーにIteratorすぎないため、それを明示的に作成してから、イテレータのremoveメソッドを使用できます。

Iterator<Message> it = messagesList.iterator();
while (it.hasNext()) {
    if (it.next().getId().length == 0) {
       it.remove();
    }
}

別の方法として、逆方向に実行して にインデックスを付ける単純なforループを使用することもできますArrayList(get(int)は に対する安価で一定時間の操作でありArrayList、すべての に当てはまるわけではないためList)。

int index;
for (index = messagesList.length - 1; index >= 0; --index) {
    if (messagesList.get(index).getId().length == 0) {
       messagesList.remove(index);
    }
}
于 2012-10-30T11:10:53.163 に答える
3

ArrayListによって返されるイテレータは本質fail-fast的です。

このクラスの反復子とlistIteratorメソッドによって返される反復子はfail-fas次のとおりです。反復子が作成された後、反復子自体の remove メソッドまたは add メソッド以外の方法でリストが構造的に変更された場合、反復子はConcurrentModificationException. したがって、同時変更に直面した場合、反復子は、将来の不確定な時点で恣意的で非決定論的な動作を危険にさらすのではなく、迅速かつ明確に失敗します。

iterator.remove();暗黙的ではなく明示的に反復子に基づいてループを呼び出して変更できます。

ArrayList<Message> messagesList = new ArrayList<Message>();
    if (!clearList) {
        messagesList.addAll(messages.getMessagesList());
        for (ListIterator<Message> iterator = messagesList.listIterator();iterator.hasNext();) {
            Message message = iterator.next();
            if (message.getId().length() == 0) {
                iterator.remove();
            }
        }
    }

参考文献:

  1. For-Each ループ
  2. ArrayList Java ドキュメント
于 2012-10-30T11:12:50.330 に答える
3
 for (Message msg : messagesList) {
                if (msg.getId().length() == 0) {
                    messagesList.remove(msg);
                }
        }

このコードでは、一度に使用すると、エラーに直面している理由messagesListからデータも削除されます同時変更例外..messagesList

ここであなたの問題を解決するためのより良い方法です。すべてのデータを1つの配列リストにコピーして、メインリストからすべてのデータを削除および削除します。

Message removeMsg = new ArrayList<Message>();
 for (Message msg : messagesList) {
                    if (msg.getId().length() == 0) {
                        removeMsg.add(msg);
                    }
            }

messagesList.removeAll(removeMsg);
于 2012-10-30T11:14:34.763 に答える
2

forループは、反復しているリストを変更している可能性があります。これが例外の原因です。変更が条件に基づいているという事実は、リストが必ずしも変更されるとは限らないため、常に発生するとは限らない理由です。

を使用することは、方法Iteratorを提供する可能な解決策です。remove()

于 2012-10-30T11:10:51.613 に答える
0

-問題は同期に関連していませんが、直面しているConcurrentModificationの問題は、コレクションが間違ったタイプのオブジェクトを取り込むのを防ぐために使用されます。

例えば:

Catオブジェクトが犬のコレクションタイプに入らないようにします。

-この問題は、Iterator

ArrayList<Message> messagesList = new ArrayList<Message>();

Iterator<Message> itr = messagesList.iterator();

while(itr.hasNext()){

 Message m = itr.next();

 itr.remove();   // Its remove() method of Iterator NOT ArrayList's

}
于 2012-10-30T11:19:39.170 に答える
0

Synchronize静的メソッドはどのインスタンスにも属していないため、このクラスにはキーワードを使用する必要があります

于 2012-10-30T11:14:15.007 に答える