2011-01-10 3 views
1

Я стараюсь найти проблему в этом Java-коде, но я не могу ее найти - вы можете мне помочь?Loop через ThreadGroup - пожалуйста, помогите мне отладить

Надеюсь, код, который я предоставляю, достаточно, но при необходимости отправлю больше.

Далее извиняюсь, я не сделал минимального примера.

game.getGroupPlayers().list(); 
MoverThread[] playerThread = game.getPlayers(); 
System.out.println(playerThread.length); 
for (int i = 0; i < playerThread.length; i++) { 
    try { 
     System.out.println(i + " -> " +playerThread[i].toString()); 
     returnString += playerThread[i].toString() + "\n"; 
    } catch(NullPointerException e) { 
     System.out.println("Problem at i = " + i); 
     e.printStackTrace(); 
    } 
    game.getGroupPlayers().list(); 
} 

иногда дает мне следующий вывод:

java.lang.ThreadGroup [имя = Игроки, maxpri = 10]
игрока-0: 113
игрока-1: 277
Игрок-2: 0
0 -> Игрок-0: 113
1 -> Игрок-1: 277
Проблема при я = 2
java.lang.NullPointerException
на Referee.goalFound (Referee.java:70)
на DebugTestReferee.goalFound (DebugTestReferee.java:42)
в Player.checkGoal (Player.java:61)
на Player.run (Player.java:94)
в java.lang.Thread.run (Thread.java:636)
java.lang.ThreadGroup [имя = Игроки, maxpri = 10]
Player- 0: 113
Игрок-1: 277
Игрок-2: 0

[править] вот источник getPlayers()

/* 
* post returns the games players as an array 
*/ 
public MoverThread[] getPlayers() { 
synchronized(movers) { 
    MoverThread[] playerList = new MoverThread[players.activeCount()]; 
    players.enumerate(playerList); 
    return playerList; 
} 
} 

[править] вот как генерируется игроки

private ThreadGroup movers; 
private ThreadGroup players; 
private ThreadGroup ghosts; 

private Observer observer; 

/* 
* constructor 
*/ 
public Game(Maze maze, Referee referee) { 
this.maze = maze; 
this.referee = referee; 
threadList = new ArrayList<MoverThread>(); 
movers = new ThreadGroup("Movers"); 
players = new ThreadGroup(movers, "Players"); 
ghosts = new ThreadGroup(movers, "Ghosts"); 
observer = null; 
} 

[править]

Вот как я называю метод, который порождает проблему:

/* 
* post checks if the players thread was interrupted - if not if hostfield pretends to be a goal the game gets stopped and referee is called to perform "goal-found-actions" 
*/ 
private void checkGoal() { 
if (!getThread().isInterrupted()) { 
    synchronized(getGame().getMovers()) { 
     if (!getThread().isInterrupted()) { 
      if (getHostField().isGoal()) { 
       Field goal = getHostField(); 
       getGame().getReferee().goalFound(this, goal); 
       getGame().setGameOver(); 
      } 
     } 
    } 
} 
} 

и вот весь goalFound()

/* 
* post action to be performed if a player finds a goal 
* print some information 
*/ 
public void goalFound(Player player, Field at) { 
//FIXME get the Bug!!! 
String returnString = "Game over - player " + player.getName() + " found a goal on (" + at.getPos()[0] + ", " + at.getPos()[1] + ")!\n"; 
game.getGroupPlayers().list(); 
MoverThread[] playerThread = game.getPlayers(); 
System.out.println(playerThread.length); 
for (int i = 0; i < playerThread.length; i++) { 
    try { 
     System.out.println(i + " -> " +playerThread[i].toString()); 
     returnString += playerThread[i].toString() + "\n"; 
    } catch(NullPointerException e) { 
     System.out.println("Problem at i = " + i); 
     e.printStackTrace(); 
    } 
} 
game.getGroupPlayers().list(); 
returnString += game.mazeString(); 
System.out.println(returnString); 
} 
+0

Исключение не вызывается в коде, вызванном из этого цикла ... похоже, что исключение происходит в одном из других потоков и получает вывод одновременно с циклом, который вы показываете. Посмотрите в класс 'Рефери' 70, где NPE бросается. –

+0

Referee.java line 70 - System.out.println (i + "->" + playerThread [i] .toString()); – speendo

ответ

0

Я нашел решение - или, может быть, больше обходной путь ...

рядом с использованием ThreadGroups Я храню темы в ArrayList Aswell (возможно, вектор был бы еще лучше, но я в порядке с ArrayList) ,

Я не знаю почему, но когда я пытаюсь вызвать все темы в ThreadGroup, часто бывает, что некоторые потоки не учитываются. Однако с ArrayList он работает отлично.

Было бы интересно, почему ThreadGroups не работают должным образом и для чего они нужны в этом случае.

1

game.getPlayers(); возвращается MoverThread[] длиной 3, но третий один null.

+0

да, вот что говорит ошибка. однако это не может быть ... см. edit – speendo

+1

Итак, тогда 'players.enumerate (playerList);' то, что не задает третий. –

+0

Сначала я хочу сказать, что очень ценю вашу помощь. Игроки - это группа Threadgroup (добавит ее в ближайшее время к моему сообщению), и поэтому игроки.enumerate (list) должны поэтому быть стандартным java-методом ... – speendo

3

Невозможно перечислить Thread s ThreadGroup. Это хорошо известный ужасный дизайн.

Между звонками и ThreadGroup.enumerate(Thread[]) потоки, возможно, начались или умерли. Лучшее, что вы можете сделать, это добавить фактор вымывания activeCount при распределении массива. Если возвращаемое значение соответствует длине массива, возможно, вы пропустили некоторые из них и должны повториться с большим размером массива (возможно, фактором больше, а не просто добавлением константы). В случае успеха вам необходимо соответствующим образом обрезать массив (или рассматривать его как таковой).

+0

Я открыт для любого решения! В конкретном случае, однако ни один поток не должен был начинаться или умирать из-за двух причин: 1. потоки генерируются только в начале программы, потоки только убиваются в конце программы 2. (и, что более важно) I вызовите этот метод, когда двигатели синхронизированы (я отредактирую свой источник, чтобы показать это). Однако, если это может решить мою проблему - скажите, пожалуйста! – speendo

+0

Я не думаю, что определена семантика использования блокировки 'ThreadGroup'. В реализации «Thread» Sun/Oracle поведение немного неожиданно. В общем, это плохая идея расширить «Thread», и использование «ThreadGroup» обычно не является отличной идеей. Использование подтипа 'Thread' для массива' Thread [] ', переданного в' ThreadGroup.enumerate', является немного опасным, и оказывается неопределенным, что происходит, если присутствует неуместный подкласс 'Thread' (он выдает' ArrayStoreException' из внешний вид источника Sun/Oracle). –

+1

Блох выступает против использования 'ThreadGroup' в * Эффективной Java *. См. Http://stackoverflow.com/q/3265640/545127 – Raedwald

Смежные вопросы