0

良い一日、

Java の LinkedList で同時実行の問題が発生しています。「Listeners」と呼ばれる「MessageHandlers」のメンバー変数 LinkedList として「Connection」と呼ばれるオブジェクト型があります。次に、2 つの異なるスレッドがあり、1 つは同じ LinkedList を変更し、もう 1 つは反復します。

同期化されたコード ブロックを使用することを提案する StackOverflow の他の多くの質問を見てきましたが、それがすべてを助けているようには見えません。また、LinkedList を同時リンク リストとして作成しようとしましたが、まだ受信しています

 Exception in thread "Thread-1" java.util.ConcurrentModificationException

例外。他に試してみるべき提案はありますか?これが私のコードの一部です...

public synchronized Object ReadObject() throws java.io.IOException
{
    Object obj = null;

    try
    {
        obj = input.readObject();

        synchronized(listeners)
        {
            Iterator<MessageHandler> i = listeners.iterator();

            while(i.hasNext())
            {
                i.next().MessageReceived(obj, this);
            }
        }
    } 
    catch (IOException e)
    {   
        e.printStackTrace();
        throw e;
    } 
    catch (ClassNotFoundException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return obj;
}

上記のコードは、接続オブジェクト内にあります。ソケットからデータを読み取るソケットの ObjectInputStream を持つ関数から呼び出されます。「入力」は ObjectInputStream のインスタンスです。

public void addNewLoggedInUser(User user) throws Exception
{
    for(User u:loggedInUsers)
    {
        if(u == user)
        {
            throw new Exception("That user is already logged in");
        }
    }

    //Add the new users
    loggedInUsers.add(user);

    synchronized(user.getConnection().getListeners())
    {
        user.getConnection().getListeners().add(this);
    }

    this.SendGameStatusUpdateToAllLoggedinPlayers();
}

次に、メソッドuser.getConnection().getListeners().add(this)を呼び出すと、例外が発生します。

public Connection()
{
    //Initialize the variables to NULL
    socket              = null;
    output              = null;
    input               = null;
    receiveThread       = null;
    runReceiveThread    = false;
    listeners           = Collections.synchronizedList(new LinkedList<MessageHandler>());

    //Handle the ID counter. Now we have a unique ID for every connection that comes in
    connectionID = counterID;
    counterID = counterID + 1;
}

これは接続クラスのコンストラクターです。Collections.synchronizedListに注意してください

何か案は?ご助力ありがとうございます!

4

3 に答える 3

2

java.util.ConcurrentModificationException実際にはスレッドの問題ではありません。これは、イテレータによってロックされているリストの変更が原因です。addNewLoggedInUser()から電話していると思いますMessageReceived()。これにより、呼び出し元の関数が既にリンクリストに反復子ロックを持っているため、同時変更例外が発生します。

于 2012-06-15T03:48:57.210 に答える
0

ブロックはsynchronized機能するはずです。ReadObject synchronizedリストを変更するブロック内から呼び出されるメソッドにアクティビティがあると思います。(またはリスナー リストを更新する可能性のあるその他のメソッド)MessageHandlerへの呼び出しまたはチェーンのいずれかを実行しますか?addNewLoggedInUser

その場合、スレッドはすでにブロックによってグラブされたモニターを持っており、 でReadObject synchronizedブロックに入ることができますaddNewLoggedInUser

于 2012-06-15T03:47:30.267 に答える