[英]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.