循环通过ThreadGroup - 请帮我调试

时间:2011-01-10 22:29:18

标签: java multithreading for-loop

我努力在这个Java代码中找到问题,但我找不到它 - 你能帮助我吗?

我希望我提供的代码足够,但如果有必要,我会发布更多代码。

此外,我道歉,我没有做出一个最小的例子。

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]
      Player-0:113
      Player-1:277
      Player-2:0
  3
  0 - &gt; Player-0:113
  1 - &gt; Player-1:277
  i = 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
      Player-1:277
      Player-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);
}

3 个答案:

答案 0 :(得分:3)

没有一种很好的方法来枚举Thread的{​​{1}}。这是一个众所周知的可怕设计。

在调用ThreadGroupThreadGroup.activeCount之间,线程可能已经启动或死亡。您可以做的最好的事情是在分配数组时添加一个软件因子ThreadGroup.enumerate(Thread[])。如果返回的值与数组长度匹配,那么您可能错过了一些并且应该以更大的数组大小重复(可能是更大的因子,而不是仅添加常量)。如果成功,您需要适当修剪阵列(或者将其视为这样)。

答案 1 :(得分:1)

game.getPlayers();返回MoverThread[]长度为3,但第三个为null

答案 2 :(得分:0)

我找到了解决方案 - 或者更多的解决方法......

除了使用ThreadGroups之外,我还将我的线程存储在ArrayList中(也许Vector会更好,但我对ArrayList很好)。

我不知道为什么,但是当我尝试调用ThreadGroup中的所有线程时,经常发生一些线程被遗漏。但是,使用ArrayList可以正常工作。

有趣的是,为什么ThreadGroups不能按预期工作,在这种情况下我们需要它们。