我有一个java / blazeds应用程序,它保留了一个数组“ _games ”,这是2个玩家订阅相同的blazeds主题。我看到的问题是连接尝试成功的比例不到40%,到目前为止我调试问题的努力都没有成功 - 它似乎无声地抛出,行为是随机的,除了第一对似乎有更多的运气连接比后续尝试。我看到了 ConcurrentModificationException ,我在这个主题上看到的内容表明我的代码存在并发问题。
在这种情况下,我在一个线程中迭代一个数组“_games”,我想知道如何安全地执行此操作,因为其他客户端将尝试随机访问此变量。
更新#2:
在调试线程内部的for循环时,看起来当前项目始终是相同的,因此迭代器没有前进和/或被后续请求重置,因此我总是= 0,或者如果使用for(游戏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类中迭代_games,也在GameServiceThread中迭代。首先,当新客户端向服务发送远程游戏对象时,我在同一集合内迭代以向每个游戏接收者发送消息。每个游戏内部都是一个集合,我用它来确定游戏是否已满 - 如果它是一个新的游戏()被创建。
答案 0 :(得分:1)
您可以在列表本身上进行同步。
@Override
public void run() {
this.running = true;
while (this.running)
{
synchronized (_games) {
for (Game g: _games) {
//do work
}
}
}
}
答案 1 :(得分:0)
您可能需要synchronize
访问_games
列表。
这是docs.oracle.com上的Synchronization教程。
答案 2 :(得分:0)
您可以从使用线程安全列表开始,例如:
List list = Collections.synchronizedList(new ArrayList(...));
检查ArrayList javadoc以获取更多信息。
答案 3 :(得分:0)
synchronized(_games) {
for (Game g: _games)
{
//do work
}
}
OR
synchronized(getClass()) {
for (Game g: _games)
{
//do work
}
}
都会奏效。
根据你在sendGameUpdate中所做的事情,你可能还必须在同一个对象上进行同步。