0

メインスレッドとClientThreadがあります...メインスレッドでは、ユーザーがサーバーに接続すると、ClientThreadのメソッドが呼び出されます。

    try {
        Socket socket = server.accept();
        clientThread.addClient(socket);
    } catch(Exception e) {
        e.printStackTrace();
    }

ClientThreadのメソッドは、ArrayListにコンテンツを追加します

public void addClient(Socket socket) {
    clientSockets.add(socket);
}

ClientThreadは、すべてのフレームで次のコードも実行します。

        for (Socket socket : clientSockets) {
            label.setText(socket.toString());
        }

どういうわけか私はこのjava.util.ConcurrentModificationException行でこのエラーを取得しfor (Socket socket : clientSockets) {ます...

質問:なぜこのエラーが発生するのですか、どうすれば修正できますか?

4

2 に答える 2

4

の反復中clientSocketsにの構造を変更することは許可されていないため、へのアクセスを同期する必要があります。List

簡単な解決策はclientSockets、同期されたコレクションを作成し、反復の前に明示的に同期することです。

List<Socket> clientSockets = Collections.synchronizedList(new ArrayList<Socket>());


//...when setting the labels:
synchronized (clientSockets) {
    for ( Socket socket : clientSockets ) {
        label.setText(socket.toString());
    }
}

リストを反復処理する場合は常に同じことを行う必要があります。

CopyOnArrayListより多くのメモリを使用し、わずかに古いデータを提供する可能性を犠牲にして、同期する必要のないのようなものを使用することを検討することもできます。

于 2012-09-09T13:49:58.533 に答える
0

Javadocによると、「複数のスレッドが同時にArrayListインスタンスにアクセスし、少なくとも1つのスレッドがリストを構造的に変更する場合は、外部で同期する必要があります(構造的変更とは、1つ以上の要素を追加または削除する操作、または明示的にサイズを変更する操作です。バッキング配列。要素の値を設定するだけでは、構造的な変更にはなりません。」

ラベルを設定するだけでは構造的な変更ではないので、それが例外の原因かどうかはわかりません。

于 2012-09-09T14:16:21.243 に答える