0

I need to create 2 classes, Class Player and Class Referee which implement Runnable interface(Basically, create threads).

The order in which the threads have to be executed are

Referee Player 1 or 2 Referee Player 1 or 2 and so on..

Here, is the solution that I came up with, but, the order doesn't seem to happen. Players keep playing even before referee completes checking.

``

public class a {

      public static synchronized void main(String[] args) throws InterruptedException {

         ready = false;
         finish = false;

         ExecutorService executorService = Executors.newCachedThreadPool();

         executorService.execute(new Referee());
         executorService.execute(new Player(1));
         executorService.execute(new Player(2));

         Thread.sleep(1000);
         executorService.shutdown();
         executorService.awaitTermination(1, TimeUnit.MINUTES);
    }

   /*....FOLLOWED BY GETTER AND SETTER METHODS
   *
   *
   */

}

class Player implements Runnable{

    public synchronized void play() throws InterruptedException{

        //continue playing unless game is over
        while(true)
        {

                 while( (a.getReady()) != true){

                     wait();
                 }
              /***
              *
              *
              *
              execute some code to play
              **/

              //Change the value of the condition variable for the referee to start executing
                a.putReady(false);

        }
    }       



    @Override
    public void run() {

        try {
            play();
        } catch (InterruptedException ex) {
            Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

class Referee implements Runnable{

    public synchronized void check() throws InterruptedException {

            while(true)
            {
                /****INITIALIZING THE GAME***/

                while(a.getReady())
                    wait();


                 //If some player has won, releasing locks and exiting the threads                             
                   if(winner != 0)
                   {

                       a.putReady(true);
                       a.putFinish(true);
                       return;
                   }


                   //If the boards are full and ends in a draw
                   else if(count_plays >= 42)
                   {
                       System.out.print("\n Board is full. Its a draw!!\n");
                       a.putReady(true);
                       a.putFinish(true);
                       return;
                   }

                   //If there is more space on the board to play
                   else 
                   {
                       System.out.print("\nNo player has won, let the play resume!!\n");
                      //Thread.sleep((long)100);  
                   }


                   /* Code for checking if there has been a winner

                   *
                   *
                   */


                 a.putReady(true);
                 notify();
                }
            }

    @Override
    public void run(){
        try {
            check();
        } 
        catch (InterruptedException ex) {
            Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
`

I understand that threads of different objects cannot be synchronized and there is no point in serializing the code that is under synchronization. This is a task that I have been assigned. In the above code, Players play simultaneously even after providing a set of condition variables and do not allow thread of the referee to check for the winner each time they play.

Please, give me an outline of the code to provide such an output using synchronized method, notify() and wait().

itsme.cvk
  • 123
  • 1
  • 8
  • 3
    `synchronized run()` should work just fine. However, note that this provides mutual exclusion *only* on that `Runnable` instance, not between instances; you will only get locking if you run the same `Runnable` instance multiple times simultaneously. – Andy Turner Dec 04 '15 at 23:31
  • 1
    related http://stackoverflow.com/questions/7313657/should-you-synchronize-the-run-method-why-or-why-not – Maciej Chałapuk Dec 04 '15 at 23:31
  • You are mistaken. It is permitted. It is also pointless. – user207421 Dec 05 '15 at 00:00
  • 2
    am I the only one who thinks it's a bad design to begin with? a player and referee should be regular objects. it is not their responsibility to run in parallel! you should create a "GameEngine" class which will span threads which should do something usefull with the players and the referee. – David Haim Dec 05 '15 at 00:03
  • @DavidHaim Even I think the same too. But, that's a requirement for my assignment that i'm working on. – itsme.cvk Dec 05 '15 at 00:10

1 Answers1

2

It is allowed but rarely makes sense and would not make sense in your case. The two threads would be synchronizing on different objects which would have no effect. The point of the synchronized method is to prevent two threads from simultaneously accessing the same object. If the two players need to access some common object but you don't want the accesses to overlap you should synchronize on that object or synchronize one of the methods of that object. You should only be within a synchronized block or method for as little time as possible. synchronizing unnecessarily can lead to poor performance or deadlock.

The closest that made any sense to me was this:

a

public static class a {

    static boolean finish = false;

    public static void main(String[] args) throws InterruptedException {

        finish = false;

        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.execute(new Referee());
        executorService.execute(new Player(1));
        executorService.execute(new Player(2));

        // wait for user to press enter, just for testing
        new Scanner(System.in).nextLine();
        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.MINUTES);
    }
}

Player

public class Player implements Runnable {

    final int playernum;

    public Player(int playernum) {
        this.playernum = playernum;
    }

    @Override
    public void run() {
        try {
            while (!a.finish) {

                synchronized (a.class) {
                    for (int i = 0; i < 5; i++) {
                        Thread.sleep(1000);
                        System.out.println("player " + playernum + " does step " + i);
                    }
                }
                Thread.sleep(1000);
            }
        } catch (InterruptedException interruptedException) {
        }
    }
}

Referee

public class Referee implements Runnable {

    @Override
    public void run() {
        try {
            while (!a.finish) {
                synchronized (a.class) {
                    System.out.println("Check for winner.");
                }
                Thread.sleep(1000);
            }
        } catch (InterruptedException interruptedException) {
        }
    }
}

Notice that it is not synchronized during the entire run only during an internal block inside.

It should produce something like this:

Check for winner.
player 1 does step 0
player 1 does step 1
player 1 does step 2
player 1 does step 3
player 1 does step 4
Check for winner.
player 2 does step 0
player 2 does step 1
player 2 does step 2
player 2 does step 3
player 2 does step 4

Without synchronization you would not see all 5 steps from each player with no intervening checks or steps from the other player.

WillShackleford
  • 6,918
  • 2
  • 17
  • 33
  • As of now I'm not worried about the performance. I need to write a code using a similar structure. Can you help me with that? – itsme.cvk Dec 05 '15 at 01:07
  • Unfortunately I can not really tell from the code given what if anything needs to be synchronized. Does the current code do what you want? If not what exactly do you want and how does that differ from the results when run. We would need the code for the putReady and getReady functions. Are they static? What is the initial value of ready? The wait() and notify() are also acting on different objects so they will not be communicating. – WillShackleford Dec 05 '15 at 01:59
  • Yes, putReady and getReady functions are static and they are used to only retrieve or change the value of ready variable. The code for implementing the game works fine. I need the players to serialize with the referee just like any game. But, sometimes 2 players play concurrently without allowing the referee to check for the winner. This is all I need to do. – itsme.cvk Dec 05 '15 at 02:17
  • Initial value of ready variable is false. So, when the value of the ready variable is false, referee checks for a winner. After checking for the winner and if there isn't one, it changes the value of ready variable to true. Meanwhile, the players wait when the value of ready variable is false. This condition is mentioned in the `while (getReady()) wait() `. When referee changes the value of ready variable to true, instead of only one player being able to attain the lock , both the players are playing at the same time. I need either of the players to play the game at once. – itsme.cvk Dec 05 '15 at 02:21
  • Added example code to answer. – WillShackleford Dec 05 '15 at 13:03