Why using wait() and notify() is much better option to solve busy spin?

Because in case when we use sleep() method, thread will wake up again and again after specified sleep time until boolean variable is true. But, in case of wait() thread will wake up only when when notified by calling notify() or notifyAll(), hence end up consuming CPU in best possible manner

Program - Consumer Producer problem with busy spin >

Note: In below program, Producer will allow consumer to consume only when 10 products have been produced (i.e. when production is over)

Consumer thread continuously execute (busy spin) in while loop (tillproductionInProcess is true) and wait for producer thread to get over. Once producer thread has ended it will make boolean variable productionInProcess false and busy spin will be over.

while(this.prod.productionInProcess){

System.out.println("BUSY SPIN - Consumer waiting for production to get over");

}

But how performance is impacted in this program?

Performance is impacted because consumer thread is continuously executing and unnecessarily consuming CPU. It would have been better if consumer would have called wait() and waited until being notified by producer. So, consumer thread consumes CPU unnecessarily and didn’t allow producer to utilize complete CPU better performance.

import java.util.ArrayList;

/* Producer will allow consumer to

* consume only when 10 products have been produced (i.e. when production is over).

*/

class Producer implements Runnable{

booleanproductionInProcess;

ArrayList<Integer> list;

Producer(){

productionInProcess=true; //initially Producer will be producing, so

//make this productionInProcess true.

list=new ArrayList<Integer>();

}

@Override

publicvoid run(){

for(int i=1;i<=10;i++){//Producer will produce 10 products

list.add(i);

System.out.println("Producer is still Producing, Produced : "+i);

try{

Thread.sleep(500);

}catch(InterruptedException e){e.printStackTrace();}

}

productionInProcess=false; // Once production is over, make

//this productionInProcess false.

//Production is over, consumer can consume.

}

}

class Consumer extends Thread{

Producer prod;

Consumer(Producer obj){

prod=obj;

}

publicvoid run(){

/*

* consumer will continuously loop until productionInProcess is true.

*/

while(this.prod.productionInProcess){ //BUSY SPIN

System.out.println("BUSY SPIN - Consumer waiting for production to get over.");

}

/*productionInProcess is false means production is over,

consumer will start consuming. */

System.out.println("Production is over, consumer can consume.");

int productSize=this.prod.list.size();

for(int i=0;i<productSize;i++)

System.out.println("Consumed : "+ this.prod.list.remove(0) +" ");

}

}

/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */

publicclassBusySpin{

publicstaticvoid main(String args[]){

Producer prod=new Producer();

Consumer cons=new Consumer(prod);

Thread prodThread=new Thread(prod,"prodThread");

Thread consThread=new Thread(cons,"consThread");

prodThread.start(); //start producer thread.

consThread.start(); //start consumer thread.

}

}

If we execute this program we will note in output that "BUSY SPIN - Consumer waiting for production to get over.” is printed several times.

In program consumer thread will start() and wait by calling wait() method till producer is producing. Once production is over, producer thread will call notify() method, which will notify consumer thread and consumer will start consuming.

But how performance is improved in this program?

Performance is improved because consumer thread called wait() method. Once production is over, producer thread will call notify() method, which will notify consumer thread and consumer will start consuming. So, consumer thread will not consume CPU unnecessarily and allow producer to utilize complete CPU for better performance.

import java.util.ArrayList;

/* Producer is producing, Producer will allow consumer to

* consume only when 10 products have been produced (i.e. when production is over).

*/

class Producer implements Runnable{

ArrayList<Integer> sharedQueue;

Producer(){

sharedQueue=new ArrayList<Integer>();

}

@Override

publicvoid run(){

synchronized (this) {

for(int i=1;i<=10;i++){//Producer will produce 10 products

sharedQueue.add(i);

System.out.println("Producer is still Producing, Produced : "+i);

try{

Thread.sleep(1000);

}catch(InterruptedException e){e.printStackTrace();}

}

System.out.println("Production is over, consumer can consume.");

this.notify();//Production is over, notify consumer thread

//so that consumer can consume.

}

}

}

class Consumer extends Thread{

Producer prod;

Consumer(Producer obj){

prod=obj;

}

publicvoid run(){

/*

* consumer will wait till producer is producing.

*/

synchronized (this.prod) { //NO BUSY SPIN

System.out.println("NO BUSY SPIN, Consumer waiting for production to get over.");