1

同じ blazeds トピックにサブスクライブしている 2 人のプレイヤーである配列 " _games "を保持する Java / blazeds アプリがあります。私が見ている問題は、接続試行の成功率が 40% 未満であることです。これまでのところ、問題をデバッグする私の努力は成功していません。サイレントにスローされているようで、動作はランダムです。ConcurrentModificationExceptionを見たことがありますが、このトピックについて読んだところ、コードに同時実行性の問題があることがわかりました。

この場合、スレッド内で配列「_games」を繰り返し処理しています。他のクライアントがランダムにこの変数にアクセスしようとするため、これを安全に行う方法を知りたいです。

更新#2:

スレッド内で for ループをデバッグしている間、現在のアイテムが常に同じであるように見えるため、イテレータは前進せず、後続のリクエストによってリセットされないため、 i always = 0 、または for(Game g : _games) を使用する場合、その場合、g は常に配列の最初の項目です。

ありがとう!

public class GameService {

private static List<Game> _games;
private static GameServiceThread thread;


public GameService(MessageTemplate template) {
    this.template = template;
}

public Game CreateOrJoinGame(GamePlayer player)
{

    Game currentGame = new Game();
    boolean isFull = false;
    for (Game g: _games)
    {

        ArrayCollection myCollection = g.myCollection;
        currentGame = g;
        if(!g.IsFull())
        {
            myCollection.add(player);

            if(g.IsFull())
            {
                isFull = true;
                currentGame.myCollection = myCollection;
                System.out.print("User Count..." + myCollection.size() + "\n");
            }
            break;
        }

    }
    if(isFull)
    {
        return currentGame;
    }
    else
    {
        Game creator = CreateGame(player);
        return creator;
    }
}


public void start() {
     if (thread == null) {
        if(_games == null)
        {
          _games = new ArrayList<Game>();
        }        
            thread = new GameServiceThread(this.template);
            thread.start();
     }
}
public void AddPlayer(GamePlayer player)
{
    _allPlayers.add(player);
}

// ネストされた静的スレッド クラス

public static class GameServiceThread extends Thread {

        @Override
    public void run() {

        this.running = true;
        while (this.running) 
        {
            for (Game g: _games)
            {
                 //do work
            }

        }
     }


    private void sendGameUpdate(final Game game) {}

このサービスは、情報のためだけに flex-servlet に登録されていますが、これは私の問題ではないと思います。

<bean id="gameFeedService" class="com.acme.services.GameService">
    <constructor-arg ref="defaultMessageTemplate" />
    <flex:remoting-destination />
</bean>

編集: 新しいゲームを追加する方法のコードを追加しました。GameService クラスと GameServiceThread 内で _games を反復処理します。まず、新しいクライアントがリモート ゲーム オブジェクトをサービスに送信し、同じコレクション内で反復処理を行って、各ゲーム受信者にメッセージを送信します。各ゲーム内には、ゲームがいっぱいかどうかを判断するために使用するコレクションがあります。新しい Game() が作成された場合です。

4

4 に答える 4

1

リスト自体で同期することができます。

    @Override
public void run() {

    this.running = true;
    while (this.running) 
    {
        synchronized (_games) {
            for (Game g: _games) {
             //do work
            }
        }
    }
 }
于 2012-12-01T23:55:45.550 に答える
0

スレッドセーフリストを使用して開始できます。次に例を示します。

List list = Collections.synchronizedList(new ArrayList(...));

詳細については、 ArrayListjavadocを確認してください。

于 2012-12-01T23:49:38.353 に答える
0
synchronized(_games) {            
    for (Game g: _games)
    {
        //do work
    }
}

また

synchronized(getClass()) {            
    for (Game g: _games)
    {
        //do work
    }
}

両方とも機能します。

sendGameUpdateで何をしているかによっては、同じオブジェクトでも同期する必要がある場合があります。

于 2012-12-01T23:52:09.747 に答える
0
于 2012-12-01T23:48:36.277 に答える