我使用通知错误java

时间:2013-12-08 20:57:41

标签: java multithreading

public synchronized void run(){
       while(running){
         if(!paused){
                //synchronized(CardGame.playingDeckArray){
                    playGame();
                    if ( playerNumber == CardGame.playingDeckArray.length ){
                        notifyAll();
                    }else{ 
                    try{
                        wait();
                    }catch( InterruptedException e){
                }
            }
           // }
         }
       }
    }


private void playGame(){
            switch(strategyChosen){
                case 1 : playStratOne();
                break;
                case 2 : playStratTwo();
                break;
            }
    }


private void playStratTwo(){
        try{
            Thread.sleep( 1000*playerNumber );
        }catch( InterruptedException e ){
        }

            int index = 0;
            System.out.println( getPlayerName() + " discards a " + hand[index].getCardValue() + " to deck " + playerNumber );
            Logger.addToOutput( getPlayerName(), getPlayerName() + " discards a " + hand[index].getCardValue() + " to deck " + playerNumber + "\n");
            CardGame.playingDeckArray[playerNumber-1].add( new Card( getHandValue(hand[index])));

            for( int i = 0; i < hand.length; i++){
                if ( index == hand.length-1 ){
                    hand[index] = new Card(0);
                }else{
                    hand[index] = hand[index+1];
                    index++;
                }
            }

            if ( playerNumber == 1){
                System.out.println( getPlayerName() + " draws a " + ((CardGame.playingDeckArray[playerNumber + CardGame.playersNum - 2].peek()).getCardValue()) + " from deck " + ( CardGame.playersNum ) );
                Logger.addToOutput( getPlayerName(), getPlayerName() + " draws a " + ((CardGame.playingDeckArray[playerNumber + CardGame.playersNum - 2].peek()).getCardValue()) + " from deck " + ( CardGame.playersNum ) + "\n" );
                hand[index] = CardGame.playingDeckArray[playerNumber + CardGame.playersNum - 2].poll();
            }else{
                System.out.println( getPlayerName() + " draws a " + (( CardGame.playingDeckArray[playerNumber - 2].peek()).getCardValue())  + " from deck " + ( playerNumber - 1 ) );
                Logger.addToOutput( getPlayerName(), getPlayerName() + " draws a " + (( CardGame.playingDeckArray[playerNumber - 2].peek()).getCardValue())  + " from deck " + ( playerNumber - 1 ) + "\n" );
                hand[index] = CardGame.playingDeckArray[playerNumber - 2].poll();
            }
            Logger.addToOutput( getPlayerName(), getHand() );

            System.out.println( getPlayerName()+ "'s hand is " );
            seeHand();

            checkWinner();
        }

当我用这个策略运行我的程序时,程序正常工作,直到它到达最后一个玩家线程,该线程执行其操作但似乎没有唤醒其他线程。我错误地使用了notifyAll()方法,因为调试器显示其他线程仍在等待。帮助将不胜感激。

public void run(){
       synchronized(CardGame.playingDeckArray){
       while(running){
         if(!paused){
             playGame();
                    if ( playerNumber == CardGame.playingDeckArray.length ){
                       CardGame.playingDeckArray.notifyAll();
                    } else{
                    try{        
                        while(playerNumber != CardGame.playingDeckArray.length){
                        CardGame.playingDeckArray.wait();
                    }
                    }catch( InterruptedException e){
                    }
                }
                }
            }
        }
    }

修改

我尝试了这种备用运行方法但是会发生的事情是第一个线程执行其操作,然后暂停,然后最终线程像以前一样执行其操作。

Player 1's hand is currently
10
6
6
5
2
Player 2's hand is currently
4
9
6
6
3
Player 3's hand is currently
4
6
5
6
6
Player 4's hand is currently
6
8
7
9
9
Player 5's hand is currently
9
1
5
3
4
Player 1 discards a 10 to deck 1
Player 1 draws a 5 from deck 5
Player 1's hand is 
6
6
5
2
5
Player 5 discards a 9 to deck 5
Player 5 draws a 5 from deck 4
Player 5's hand is 
1
5
3
4
5
Player 5 discards a 1 to deck 5
Player 5 draws a 3 from deck 4
Player 5's hand is 
5
3
4
5
3

2 个答案:

答案 0 :(得分:0)

您遇到丢失通知的问题。用以下代码替换你的等待代码:

while(playerNumber != CardGame.playingDeckArray.length)
  wait();

另一件事:

您是如何使用代码的?您是否实现了在您生成的线程中共享的Runnable?由于您直接在notifyAll()上致电wait()Runnable,因此您必须这样做。如果没有,你必须在线程之间共享一个锁对象!

一个例子:

// the monitor object that is shared among all the threads
final Object monitor = new Object();

// this variable has to be shared, is synchronized using the monitor object.
// you could also synchronize on this object instead of the separate monitor object.
final CardGamestate = ...

// ...
Player p = new Player(monitor);
// start the player, runs in a different thread
p.startPlaying();

假设您发布的代码位于Player类中,则需要在共享的监视器上进行同步!

或许类似以下内容等待:

synchronized(monitor) {
  // wait until condition is valid
  while(playerNumber != CardGame.playingDeckArray.length)
    monitor.wait();
}

醒来:

synchronized(monitor) {
  // playerNumber == CardGame.playingDeckArray.length has to evaluate `true`
  // finally notify the waiting thread(s)
  monitor.notifyAll(); 
}

答案 1 :(得分:0)

waitnotify函数适用于对象的监视器。这意味着,如果您拨打obj1.wait(),并且在另一个帖子obj2.notifyAll()中,等待obj1的线程将被唤醒。

您的代码不完整,但似乎您正在调用不同对象实例上的函数,因此它们无法相互唤醒。