java 在球员之间传球:多线程

doinxwow  于 2022-12-28  发布在  Java
关注(0)|答案(1)|浏览(118)

我正在写一个代码,以种通过4名球员之间编号1至4的球,所以它去1至2至3至4然后4至3至2至1.但我得到不一致的结果,我尝试了调试器,但我不能弄清楚如何移动过去的前2个线程.以下是代码:

package Ball_Game;

public class Team_A extends Thread {
    int ID;
    Ball ball=new Ball();
    String phase="First-phase";
  public Team_A(int ID, Ball ball) {
      this.ball=ball;
      this.ID=ID;
  }
 @Override 
 public void run() {
     synchronized (ball) {
     while(phase.contains("First-phase")){ 
        
             if (ID==ball.nbr_player) {
                ball.throw_ball();
                
                if(ID!=4) {
                    ball.increment();
                    System.out.println(ball.nbr_player);
                    ball.notifyAll();
                    
                }else {
                    phase="Second-phase";
                    System.out.println(phase);
                   
                }
            }else {
                try {
                    ball.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }    
        } 

    while(phase.contains("Second-phase")){ 
           
         if (ID==ball.nbr_player) {
            ball.throw_ball_back();
            if(ball.nbr_player>1) {
                ball.decrement();
                ball.notifyAll();
            }else {
                phase="First-phase";
                  
            }
        }else {
            try {
                ball.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }    
    } 
}
 }}

这是球类课

package Ball_Game;

public class Ball{
    int nbr_player=1;
    public synchronized void throw_ball() {
        System.out.println(Thread.currentThread().getName()+" :throws ball");
    }
    public synchronized void throw_ball_back() {
        System.out.println( Thread.currentThread().getName()+" :throws ball back");
    }
    public synchronized void increment() {
        nbr_player++;
    }
    public synchronized void decrement() {
        nbr_player--;
    }
}

当我尝试执行它时,它一直在线程3和4之间来回运行,而没有经过线程1和2,我不知道为什么。

vmdwslir

vmdwslir1#

唉。请修正你的语法。
球员应该接球和投球,但我看不出有任何需要一个球类。它有什么属性或逻辑。它只是像初级开发人员一样被扔来扔去。
从逻辑上讲,我看到了一个玩家和一个团队。一个玩家延长了一个线程,可以说它有一个生命。一个玩家可以接住一个球,然后把它扔给下一个玩家。下一个谁拿到球的逻辑由团队决定。当一个球传给下一个玩家时,整个团队都会得到通知,拿到球的玩家会把它传给下一个玩家。所有其他玩家都在等待。

@Override
    public void run() {
        while (!gameOver) {
            try {
                synchronized (team) {
                    if (hasBall) {
                        Player nextPlayer = team.getNextPlayer(playerId);
                        nextPlayer.catchBall();
                        hasBall = false;
                        team.notifyAll();
                    } else {
                        team.wait();
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

一个队是由球员组成的,而这个队包含了决定下一个谁拿球的逻辑。

public Player getNextPlayer(int currentPlayer) {
        switch (currentDirection) {
            case NEXT:
                if ( currentPlayer >= numPlayers) {
                    currentDirection = DIRECTION.PRIOR;
                }
                break;
            case PRIOR:
                if ( currentPlayer <= 1) {
                    currentDirection = DIRECTION.NEXT;
                }
                break;
        }
        int nextPlayer = currentDirection == DIRECTION.NEXT ? currentPlayer + 1 : currentPlayer - 1;
        return players.get(nextPlayer-1);
    }

剩下的就是家务活了。

public class Player extends Thread {
    private final Team team;
    private final int playerId;
    private boolean hasBall;
    private boolean gameOver;

    public Player(Team team, int playerId) {
        this.team = team;
        this.playerId = playerId;
        this.hasBall = false;
        this.gameOver = false;
    }

    @Override
    public void run() {
        while (!gameOver) {
            try {
                synchronized (team) {
                    if (hasBall) {
                        Player nextPlayer = team.getNextPlayer(playerId);
                        nextPlayer.catchBall();
                        hasBall = false;
                        team.notifyAll();
                    } else {
                        team.wait();
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void catchBall() {
        hasBall = true;
        System.out.println("Ball caught by " + playerId);
    }

    public void gameOver() {
        gameOver = true;
    }

    public void printState() {
        System.out.println("Player " + playerId + (hasBall ? " has ball." : " does NOT have ball."));
    }
}

以及

public class Team {
    private final int numPlayers;
    private final List<Player> players;
    private enum DIRECTION {NEXT, PRIOR}
    private DIRECTION currentDirection;

    public Team(int numPlayers) {
        this.numPlayers = numPlayers;
        players = new ArrayList<>(numPlayers);
        currentDirection = DIRECTION.NEXT;
        for (int i = 0; i < numPlayers; ++i) {
            players.add(new Player(this, i+1));
        }
    }

    public void playCatch() {
        players.forEach(Thread::start);
        players.get(0).catchBall();
        synchronized (this) {
            notifyAll();
        }
    }
    public void stopGame() {
        players.forEach(Player::gameOver);
        synchronized (this) {
            notifyAll();
        }
        players.forEach(p-> {
            try {
                p.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        players.forEach(Player::printState);
    }
    public Player getNextPlayer(int currentPlayer) {
        switch (currentDirection) {
            case NEXT:
                if ( currentPlayer >= numPlayers) {
                    currentDirection = DIRECTION.PRIOR;
                }
                break;
            case PRIOR:
                if ( currentPlayer <= 1) {
                    currentDirection = DIRECTION.NEXT;
                }
                break;
        }
        int nextPlayer = currentDirection == DIRECTION.NEXT ? currentPlayer + 1 : currentPlayer - 1;
        return players.get(nextPlayer-1);
    }
}

问题解决方案的描述对外行(产品所有者)和技术人员来说读起来都一样好,这是一件好事。

相关问题