私は接続のArrayListを持つサーバーアプリケーションを持っています。このプログラムは、複数のスレッドを使用します。メインスレッドは、閉じた接続を検出するために間隔でプロセスを実行し、アレイからそれらを削除してガベージコレクションできるようにします。次のようにHashMapから項目を削除するとConcurrentModificationExceptionが発生する
このプロセスは次のとおりです。
private void cullOtherProcessors() throws Exception {
//log.log(Level.FINE,"XMLMessageReciever:cullOtherProcessors");
List<ConnectionAppInterface> toDel = new ArrayList<ConnectionAppInterface>();
for (ConnectionAppInterface cur : m_OtherProcessors.keySet()) {
if (cur!=null) {
if (cur.isClosed()) {
//Connection is closed - we could never send a message over it
toDel.add(cur);
}
}
}
for (int c=0;c<toDel.size();c++) {
log.log(Level.FINE,"**XMLMessageReciever:cullOtherProcessors - removing closed connection");
m_OtherProcessors.remove(toDel.get(c));
}
}
私のサーバーは、数ヶ月のカップルのために走ったが、それは次のエラーでクラッシュしたログによると:
08/10/16 01:06:39 calling connect
08/10/16 01:06:39 **XMLMessageReciever:cullOtherProcessors - removing closed connection
08/10/16 01:06:39 CloseableThread: End of run for thread Socket.Connect(113726)
08/10/16 01:06:39 Checking connected
08/10/16 01:06:39 Active Threads this group: 5
08/10/16 01:06:39 getting Message Reciever
08/10/16 01:06:39 Active Threads: 8
08/10/16 01:06:39 Setting m_establishingCon
08/10/16 01:06:39 Establishing connection to robertsNode
Server Failed
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
at java.util.HashMap$KeyIterator.next(HashMap.java:1453)
at metcarob.com.common.network.xmlprotocol.XMLMessageReciever.cullOtherProcessors(XMLMessageReciever.java:57)
at metcarob.com.common.network.xmlprotocol.XMLMessageReciever.LoopIteration(XMLMessageReciever.java:98)
at metcarob.com.common.network.xmlprotocol.ConnectionManager.LoopIteration(ConnectionManager.java:48)
at metcarob.com.personalservices.singlenodeserver.Main.run(Main.java:138)
at metcarob.com.personalservices.singlenodeserver.Main.main(Main.java:398)
基本的に何かがArrayListに起こりました私はそれを介してループしていた(別の接続が確立されている可能性があります)ので、nextNodeは例外をスローします。
私はそれを回避する最善の方法を見つけようとしています。私は単にエラーをキャッチして無視することを検討しています。ミスしたスレッドは、次のループで単純に取り除かれます。私の提案する解決策は次のとおりです:
private void cullOtherProcessors() throws Exception {
//log.log(Level.FINE,"XMLMessageReciever:cullOtherProcessors");
//m_OtherProcessors
List<ConnectionAppInterface> toDel = new ArrayList<ConnectionAppInterface>();
try {
for (ConnectionAppInterface cur : m_OtherProcessors.keySet()) {
if (cur!=null) {
if (cur.isClosed()) {
//Connection is closed - we could never send a message over it
toDel.add(cur);
}
}
}
} catch (ConcurrentModificationException e) {
log.log(Level.FINE,"**XMLMessageReciever:cullOtherProcessors - ConcurrentModificationException being ignored");
}
for (int c=0;c<toDel.size();c++) {
log.log(Level.FINE,"**XMLMessageReciever:cullOtherProcessors - removing closed connection");
m_OtherProcessors.remove(toDel.get(c));
}
}
私は今このコードをサーバーに戻して、さらに数ヶ月間実行します。
これが問題の良い解決策であるかどうかを知りたいと思います。これが最初に起こるには数カ月かかり、コードは5分ごとに接続をループしますので、接続が頻繁に起こらない可能性は低いと思います。 (私はログを見て参照してください)
それは専門家が考えるものを知っていることは良いでしょう。
**これは、この質問を示唆されたが
それはない「ループ内で削除するときに、コレクションを反復ConcurrentModificationExceptionを避ける」と同じです。私のコードでは、HashMapを反復処理している間にアイテムを削除しないで、代わりにマップを反復して、削除するアイテムを一時配列に格納します。私はその後、配列を通過し、項目を削除します。
例外を無視するのはかなりやりがいのないことです。あなたはこのユニットを取り出してスレッドで問題を再現しようとしましたか?あなたは同じデータ構造を読み書きしているので、そこに競合状態があります。同期なしのm_OtherProcessors – Paolof76
どこにm_OtherProcessorsを作成していますか? –
あなたのエラーはマルチスレッドに関係していますか? ConcurrentModificationExceptionはスレッドとは関係ありません。マルチスレッドのためにエラーが発生した場合でも、エラーをキャッチしても、同時データ構造を使用しない場合の影響はありません。 –