Java Thread Interaction: use of wait and notify

In this blog, my main intention to introduce the thread interaction based on the java.lang.wait() and java.lang.notify()/notifyAll() methods. Anyway, I would keen to keep the things simple.

It is not difficult to visualize one of the playground trainings you had participated. There is one trainer and number of players. All the players are waiting for the ball which has been thrown by the instructor. One person can acquire ball at once and he will re-throws the ball back to the trainer. To make the things simple, suppose a player, who acquired the ball, has been pulled out from the field.

For the design, we have two factors to model

  1. The behavior between Trainer and the players
  2. The ownership of the ball

In the first case players are waiting for the trainer’s notification to acquire the ball, anyway in this competition thread scheduler decide who should get the ball, mean no special priority (all the Player threads are in the same priority level). To win the competition at that point, only one has to acquire the ball which is the second factor.

First case we have handle with the wait() and notify() thread interaction methods.

package com.ojitha.game;
/**
 * Player is active class which is expecting turn to have the ball to
 * practice. 
 * @author Ojitha
 *
 */
public class Player implements Runnable {

	Trainer trainer;
	Ball ball;

	public Player(Trainer trainer) {
		this.trainer = trainer;
	}

	//to keep simplicity only one chance has given for each player
	@Override
	public void run() {
		//wait for the trainer until the ball has successfully being acquired 
		//by the player
		synchronized (this.trainer) {
			do {
				try {
					//wait until trainer inform to activate
					this.trainer.wait();
				} catch (InterruptedException e) {

					e.printStackTrace();
				}
				//try to catch the ball threw by the trainer
				//if ball is not acquired then return is null
				ball = this.trainer.throwBall();
				
				
			} while (ball == null);

			//ball is successfully acquired
			System.out.println("Playr " + Thread.currentThread().getName()
					+ " Playing with the ball");

			synchronized (this.ball) {
				//throw back the ball to the trainer
				ball.notify();
				System.out.println("Playr " + Thread.currentThread().getName()
						+ " Release ball...");
			}

		}
	}

}

As shown in the above Player.java, Players are waiting for the Trainer notification. But only one person can get the ball via throwBall() as shown in the following Trainer.java source.

package com.ojitha.game;

public class Trainer implements Runnable {

	//ball to throw 
	Ball ball;
	//number of players decide number of turns by the trainer
	int numberOfPlayers;

	public Trainer(Ball ball) {
		this.ball = ball;		
	}
	
	public void setNumberOfPlayers(int numberOfPlayers){
		this.numberOfPlayers = numberOfPlayers;
	}

	@Override
	public void run() {

		int i=0;
		while (i < numberOfPlayers) {
			synchronized (this){
				System.out.println("Trainer throw the ball to everybody ...");
				//set the ball to acquired by the player
				ball.delivered=false;
				//wake up all players
				notifyAll();
			}
			//wait till ball is re-thrown by the player who has currently
			//hold the ball
			synchronized (ball) {
				try {
					System.out.println("Trainer waiting ...");
					ball.wait();
					System.out.println("Trainer get the ball...");
					
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			i++;

		}

	}

	/**
	 * Ball to be thrown by the trainer on request of player
	 * Only one player can acquire a ball at a time, Others has to wait till
	 * ball is available that is ball.delivered == false.
	 * @return
	 */
	public synchronized Ball throwBall() {

		if (!ball.delivered){
			ball.delivered=true;
			return this.ball;
		}
		
		else return null;
	}

}

The method throwBall() allows one Player to acquire the ball at once by setting the property Ball.delivered to true. Player is allowed to acquire the ball only if nobody has already acquired the ball. Anyway, first Player who has entered to the method will acquired the ball, other Players has to wait for the next round as shown in the “while” loop in the Player.java source.

package com.ojitha.game;

public class Ball {
	//Ball has two states
	// 1. acquired (delivered == true)or
	// 2. not acquired (delivered == false)
	//Only one person can acquire the ball once
	public boolean delivered=false;

}

Ball class has one public property which will be set to the false when it is free to acquired by one of the Players. Ball is free to acquire when it is with the Trainer always.

package com.ojitha.game;

public class Trainer implements Runnable {

	//ball to throw 
	Ball ball;
	//number of players decide number of turns by the trainer
	int numberOfPlayers;

	public Trainer(Ball ball) {
		this.ball = ball;		
	}
	
	public void setNumberOfPlayers(int numberOfPlayers){
		this.numberOfPlayers = numberOfPlayers;
	}

	@Override
	public void run() {

		int i=0;
		while (i < numberOfPlayers) {
			synchronized (this){
				System.out.println("Trainer throw the ball to everybody ...");
				//set the ball to acquired by the player
				ball.delivered=false;
				//wake up all players
				notifyAll();
			}
			//wait till ball is re-thrown by the player who has currently
			//hold the ball
			synchronized (ball) {
				try {
					System.out.println("Trainer waiting ...");
					ball.wait();
					System.out.println("Trainer get the ball...");
					
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			i++;

		}

	}

	/**
	 * Ball to be thrown by the trainer on request of player
	 * Only one player can acquire a ball at a time, Others has to wait till
	 * ball is available that is ball.delivered == false.
	 * @return
	 */
	public synchronized Ball throwBall() {

		if (!ball.delivered){
			ball.delivered=true;
			return this.ball;
		}
		
		else return null;
	}

}

Above code nippiest show the client who has run this application and generate the following output. There are five Players named as “p0”, “p1” up to the “p4”.

Trainer throw the ball to everybody ...
Trainer waiting ...
Playr p3 Playing with the ball
Playr p3 Release ball...
Trainer get the ball...
Trainer throw the ball to everybody ...
Trainer waiting ...
Playr p1 Playing with the ball
Playr p1 Release ball...
Trainer get the ball...
Trainer throw the ball to everybody ...
Trainer waiting ...
Playr p4 Playing with the ball
Playr p4 Release ball...
Trainer get the ball...
Trainer throw the ball to everybody ...
Trainer waiting ...
Playr p2 Playing with the ball
Playr p2 Release ball...
Trainer get the ball...
Trainer throw the ball to everybody ...
Trainer waiting ...
Playr p0 Playing with the ball
Playr p0 Release ball...
Trainer get the ball...

Remember this output is arbitrary, which may be entirely different in the next execution due to the uncertainty of Java threads.

Comments

Popular posts from this blog

How To: GitHub projects in Spring Tool Suite

Spring 3 Part 7: Spring with Databases

Parse the namespace based XML using Python