在Java使用忙旋转作为等待策略
Busy Spinning 是一种等待策略,其中一个线程等待某个条件发生,该条件将由其他某个线程设置。这里等待线程不断循环而不释放 CPU 周期。这会导致性能不佳,因为等待线程浪费了 CPU 周期。
一个非常自然地适合这种策略的经典用例是生产者-消费者问题。生产者线程将项目添加到队列中。在从队列中消费项目之前,消费者线程会一直等待,直到生产者生产了一个项目。等待时的消费者线程持有 CPU 周期,因此会浪费 CPU 资源,这些资源可用于其他线程的其他处理。
更好地理解此策略的另一个示例是 到 考虑一位顾客从比萨柜台订购比萨。下订单后,客户每 5 秒就会不断询问柜台人员是否准备好订单。在这里,等待该订单的顾客可以利用他的时间做其他活动,例如与他的朋友交谈、浏览最新消息等,而不是忙于检查他的披萨订单的状态。
例子
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 getToppings() { return toppings; }
public void setToppings(List toppings)
{
this.toppings = toppings;
}
private List toppings;
public Pizza(String base, List 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(
"Topings 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 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();
}
}
输出:
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
Topings are : [tomato, corn, cheese, olive]
输出说明:
在这个例子中,我们有 2 个实现 Runnable 接口的类。当调用PizzaMaker构造函数时,它会将布尔变量 isInProgress 设置为 true,这意味着它已收到披萨订单并且正在制作披萨。在 run() 中,它调用了比萨饼的 make()。制作披萨后,它将 isInProgress 布尔变量设置为 false。客户线程通过在 while 循环内通过布尔变量 isInProgress 检查订单状态来不断循环来进行繁忙的旋转。当 PizzaMaker 类将此变量设置为 false 时,客户线程将继续进行进一步处理。更好的方法是实现 Object 类中的 wait、notify 和 notifyAll() 方法。等待条件满足的线程将释放 CPU 资源并执行一些其他任务。当某个其他线程设置该线程正在等待的条件时,它会通过 notify() 方法通知正在等待的线程。