2012-12-01 2 views
1

배열을 유지하는 java/blazeds 응용 프로그램이 있습니다. "_games"이것은 2 명의 선수가 동일한 blazeds 주제에 가입되어 있습니다. 내가보기에이 문제는 40 % 미만의 연결 시도 성공입니다. 지금까지 문제를 디버깅 할 때 내 노력은 실패했습니다. 자동으로 던져 보이고 첫 번째 쌍이 연결보다 운이 많은 것 외에는 임의적입니다. 후속 시도. ConcurrentModificationException을 보았습니다. 주제에 대해 읽은 내용은 코드에 동시성에 문제가 있음을 나타냅니다.어떻게하면 스레드 내의 컬렉션을 안전하게 반복 할 수 있습니까?

스레드 내에서 "_games"배열을 반복하는 경우 다른 클라이언트가이 변수에 무작위로 액세스하려고 시도 할 때이 작업을 안전하게 수행 할 수있는 방법을 알고 싶습니다.

업데이트 2 :

실 내부 루프에 대한 디버깅하는 동안, = 그래서 반복자 진행되지 않고, 또는 그래서 항상 계속되는 요구에 의해 리셋되는 현재 항목이 항상 동일 나타나는 0이거나 for (Game g : _games)를 사용하면 g는 항상 배열의 첫 번째 항목입니다.

감사합니다. // 중첩 된 정적 스레드 클래스

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) {} 

나는 이것이 내 문제라고 생각하지 않습니다하지만이 서비스는 단지 정보를 원하시면 플렉스 - 서블릿에 등록되어

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); 
} 

.

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

편집는 : 새로운 게임이 추가됩니다 방법에 대한 몇 가지 코드를 추가했습니다. GameService 클래스 내부와 GameServiceThread 내부에서 _games를 반복합니다. 첫째, 새로운 클라이언트가 원격 게임 객체를 서비스에 전송할 때 동일한 컬렉션 내부를 반복하여 각 게임 수신자에게 메시지를 보냅니다. 각 게임 내부에는 게임이 꽉 찼는 지 아닌지를 결정하는 데 사용하는 컬렉션이 있습니다. 새 Game()이 생성 된 경우입니다.

+0

게임은 어떻게 '_games' 목록에 추가 되나요? –

+0

편집 추가 - 자세한 정보가 필요한지 알려주십시오. @KeithRandall – MikeW

답변

0

목록에 액세스하려면 synchronize해야 할 수도 있습니다.

다음은 docs.oracle.com의 Synchronization 자습서입니다.

0

당신은 예를 들어, 스레드 안전 목록을 사용하여 시작할 수 있습니다 추가 정보에 대한

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

확인 ArrayList javadoc합니다.

+0

원하는 동기화 만 목록 자체 (추가, 제거 등) 작업에있는 경우에만 작동합니다. 즉, 프로그램에서 코드 섹션을 원자 적으로 실행하지 않아도됩니다. – xagyg

+0

@xagyg - 네가 맞아 문제를 해결할 수는 있지만 모두 해결할 수는 없어. – minus

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

또는

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

모두 일 것.

sendGameUpdate에서 수행중인 작업에 따라 동일한 객체에서 동기화해야 할 수도 있습니다.

1

목록 자체에서 동기화 할 수 있습니다.

@Override 
public void run() { 

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