[英]how to do I safely iterate over a collection inside a thread?
I have a java / blazeds app that keeps an array " _games " which is 2 players subscribed to the same blazeds topic. 我有一个Java / blazeds应用程序,其中包含一个数组“ _games ”,该数组是2个订阅了相同blazeds主题的玩家。 The issue as I see is less than 40% of connection attempts succeed, so far my efforts at debugging the issue have been unsuccessful - it seems to throw silently , and the behaviour is random except that the 1st pair seem to have more luck connecting than subsequent attempts.I have seen a ConcurrentModificationException and what I have read on the topic suggests my code has problems with concurrency.
据我所知,这个问题少于40%的连接尝试成功了,到目前为止,我在调试该问题上的努力都没有成功-它似乎是无声的抛出,并且行为是随机的,除了第一对对似乎比连接更幸运随后的尝试。我已经看到了ConcurrentModificationException,并且在该主题上阅读的内容表明我的代码存在并发问题。
In this case I'm iterating over a array "_games" inside a thread, I'd like to know how I can do this safely as other clients will be attempting to access this variable at random times. 在这种情况下,我要遍历线程内的数组“ _games”,我想知道如何安全地执行此操作,因为其他客户端将尝试在随机时间访问此变量。
Update #2: 更新 #2:
While debugging the for loop inside the thread, it appears the current item is always the same so the iterator is not advancing and or being reset by a subsequent request so i always = 0 , or if use a for(Game g : _games) , then g is always the 1st item in the array. 在调试线程内的for循环时,似乎当前项始终相同,因此迭代器不会前进和/或被后续请求重置,因此我始终= 0,或者如果使用for(Game g:_games),那么g总是数组中的第一项。
thanks! 谢谢!
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);
}
//nested static thread class //嵌套的静态线程类
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) {}
This service is registered in flex-servlet just for info, although I don't think this is my issue. 尽管我不认为这是我的问题,但该服务仅在flex-servlet中注册以获取信息。
<bean id="gameFeedService" class="com.acme.services.GameService">
<constructor-arg ref="defaultMessageTemplate" />
<flex:remoting-destination />
</bean>
Edit : Added some code for how new games get added. 编辑 :添加了一些有关如何添加新游戏的代码。 I iterate over _games inside the GameService class and also inside the GameServiceThread.
我在GameService类以及GameServiceThread内部遍历_games。 Firstly as new clients send a remote game object to the service, and I iterate inside the same collection to send each game recipient a message.
首先,当新客户将远程游戏对象发送到服务时,我在同一个集合中进行迭代,以向每个游戏接收者发送一条消息。 Inside each game is a collection which I use to determine if the Game is full or not - if it is a new Game() is created.
在每个游戏中都有一个集合,我可以使用该集合来确定游戏是否已满-是否创建了新的Game()。
You could synchronize on the list itself. 您可以在列表本身上进行同步。
@Override
public void run() {
this.running = true;
while (this.running)
{
synchronized (_games) {
for (Game g: _games) {
//do work
}
}
}
}
You might need to synchronize
access to the _games
list. 您可能需要
synchronize
对_games
列表的访问。
Here's a Synchronization tutorial on docs.oracle.com. 这是docs.oracle.com上的同步教程。
You can start by using a thread safe List, for example: 您可以使用线程安全列表开始,例如:
List list = Collections.synchronizedList(new ArrayList(...));
Check ArrayList javadoc for further informations. 检查ArrayList javadoc以获取更多信息。
synchronized(_games) {
for (Game g: _games)
{
//do work
}
}
OR 要么
synchronized(getClass()) {
for (Game g: _games)
{
//do work
}
}
will both work. 都可以。
Depending on what you are doing in sendGameUpdate, you may have to synchornize on the same object there as well. 根据您在sendGameUpdate中执行的操作,您可能还必须在同一对象上同步处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.