簡體   English   中英

如何安全地遍歷線程內的集合?

[英]how to do I safely iterate over a collection inside a thread?

我有一個Java / blazeds應用程序,其中包含一個數組“ _games ”,該數組是2個訂閱了相同blazeds主題的玩家。 據我所知,這個問題少於40%的連接嘗試成功了,到目前為止,我在調試該問題上的努力都沒有成功-它似乎是無聲的拋出,並且行為是隨機的,除了第一對對似乎比連接更幸運隨后的嘗試。我已經看到了ConcurrentModificationException,並且在該主題上閱讀的內容表明我的代碼存在並發問題。

在這種情況下,我要遍歷線程內的數組“ _games”,我想知道如何安全地執行此操作,因為其他客戶端將嘗試在隨機時間訪問此變量。

更新 #2:

在調試線程內的for循環時,似乎當前項始終相同,因此迭代器不會前進和/或被后續請求重置,因此我始終= 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()。

您可以在列表本身上進行同步。

    @Override
public void run() {

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

您可能需要synchronize_games列表的訪問。

這是docs.oracle.com上的同步教程。

您可以使用線程安全列表開始,例如:

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

檢查ArrayList javadoc以獲取更多信息。

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

要么

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

都可以。

根據您在sendGameUpdate中執行的操作,您可能還必須在同一對象上同步處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM