Busy Spinning is a wait strategy in which one thread waits for some condition to happen which is to be set by some other thread. Here the waiting thread loops continuously without releasing the CPU cycles. This leads to bad performance as the CPU cycles are wasted by a waiting thread.
A classic use case that fits this strategy very naturally is the producer-consumer problem. The producer thread adds items to a queue. The consumer thread waits until an item is produced by the producer before consuming items from the queue. The consumer thread while waiting holds the CPU cycles and thus there is wastage of CPU resources which can be used for some other processing by other threads.
Another example to better understand this strategy is to consider a customer ordering pizza from a Pizza counter. After placing an order, the customer keeps asking the person at the counter if his order is ready every 5 seconds. Here, the customer waiting for this order can utilize his time doing other activities like talking to his friends, browsing the latest news, and so on, instead of busy spinning on the status check of his pizza order.
Example
Java
// Java Program to illustrate Busy Spinning as Wait // Strategy // Importing input output classes import java.io.*; // Importing List class from java.util package import java.util.List; // Class 1 // Helper class public class Pizza { private String base; public String getBase() { return base; } public void setBase(String base) { this .base = base; } public List<String> getToppings() { return toppings; } public void setToppings(List<String> toppings) { this .toppings = toppings; } private List<String> toppings; public Pizza(String base, List<String> toppings) { super (); this .base = base; this .toppings = toppings; } public void make() { System.out.println( "Making pizza" ); } } // Class 2 // Helper class public class Customer implements Runnable { PizzaMaker pizzaMaker; public Customer(PizzaMaker pizzaMaker) { this .pizzaMaker = pizzaMaker; } public void run() { while ( this .pizzaMaker.isInProgress) { System.out.println( Thread.currentThread().getName() + ":-Pizza order complete??" ); System.out.println( "--Busy Spinning---" ); try { Thread.sleep( 1000 ); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println( "Received the ordered pizza:-" + Thread.currentThread().getName()); System.out.println( "Base of the pizza is : " + pizzaMaker.pizza.getBase()); System.out.println( "Toppings are : " + pizzaMaker.pizza.getToppings()); } } // Class 3 // Helper class public class PizzaMaker implements Runnable { Pizza pizza; boolean isInProgress; public PizzaMaker(Pizza pizza) { this .pizza = pizza; this .isInProgress = true ; } public void run() { System.out.println( "Pizza order in progress" ); pizza.make(); try { Thread.sleep( 3000 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println( " Making of pizza with base :" + this .pizza.getBase() + " and toppings as " + this .pizza.getToppings() + " is complete :- " + Thread.currentThread().getName()); this .isInProgress = false ; } } // Class 4 // Main class class GFG { // Main driver method public static void main(String[] args) { // String base = "thick crust base" ; // Creating a List of String type List<String> toppings = new ArrayList<>(); // Adding elements to the object toppings.add( "tomato" ); toppings.add( "corn" ); toppings.add( "cheese" ); toppings.add( "olive" ); Pizza pizza = new Pizza(base, toppings); PizzaMaker pizzaMaker = new PizzaMaker(pizza); Customer customer = new Customer(pizzaMaker); Thread pizzaMakerThread = new Thread(pizzaMaker, "pizzaMakerThread" ); Thread customerThread = new Thread(customer, "customerThread" ); pizzaMakerThread.start(); customerThread.start(); } } |
Output:
Pizza order in progress Making pizza customerThread:-Pizza order complete?? --Busy Spinning--- customerThread:-Pizza order complete?? --Busy Spinning--- customerThread:-Pizza order complete?? --Busy Spinning--- Making of pizza with base :thick crust base and toppings as [tomato, corn, cheese, olive] is complete :- pizzaMakerThread Received the ordered pizza:-customerThread Base of the pizza is : thick crust base Toppings are : [tomato, corn, cheese, olive]
Output explanation:
In this example, we have 2 classes that implement the Runnable interface. When the PizzaMaker constructor is invoked, it sets the boolean variable isInProgress as true, which means that it has received the pizza order and making of pizza is in progress. In run() it invokes the pizza’s make(). Once pizza is made, it sets the isInProgress boolean variable to false. The Customer thread does a busy spin by looping continuously inside the while loop checking for the status of the order through the boolean variable isInProgress. When the PizzaMaker class sets this variable to false, the customer thread continues with further processing. A better approach would be to implement the wait, notify, and notifyAll() methods from the Object class. The thread waiting for a condition to be satisfied will release CPU resources and perform some other tasks. When some other thread sets this condition for which the thread was waiting, it notifies the waiting thread through notify() method.