多线程开发经典操作案例,生产者-消费者,生产者不断生产产品,消费者不断取走产品
案例场景:
饭店里有一个厨师和一个服务员,这个服务员必须等待厨师准备菜。当厨师准备好时,他会通知服务员。之后服务员上菜,然后返回继续等待。这是一个任务协作的示例,厨师代表生产者,服务员代表消费者。
Food.java (需要生产的食物)
package com.lemon.servers;
/**
* 食物:
* @author lemonsun
*/
public class Food {
private String name;
private String desc;
private boolean flag = true; //true可以生产、false可以消费
/**
* 生产食物:
* @param name 需要的产品
* @param desc 产品的描述
*/
public synchronized void setFood(String name,String desc){
//不能生产 则让出CPU时间片、释放锁也就是解锁
if(!flag){
try {
this.wait(); // 线程进入等待状态,释放监视器的所有权(对象锁)
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setName(name);
try {
Thread.sleep(500); //休眠500毫秒 模拟生产
} catch (InterruptedException e) {
e.printStackTrace();
}
setDesc(desc);
this.flag = false; //改变标记
this.notify(); //唤醒等待的线程(随机的其中一个)
}
/**
* 消费食物:
*
*/
public synchronized void getFood(){
//不能消费 则让出CPU时间片、释放锁也就是解锁
if(flag){
try {
this.wait(); //线程进入等待状态,释放监视器的所有权(对象锁)
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(500); //休眠500毫秒 模拟消费
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( getName() + "->" + getDesc());
this.flag = true; //改变标记
this.notify(); //唤醒等待的线程(随机的其中一个)
}
public Food(String name, String desc) {
this.name = name;
this.desc = desc;
}
public Food() {
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDesc() { return desc; }
public void setDesc(String desc) { this.desc = desc; }
@Override
public String toString() {
return "Food{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
Producter.java(生产者:厨师)
package com.lemon.servers;
/**
* 生产者:厨师
* @author lemonsun
*/
public class Producter implements Runnable{
private Food food;
public Producter(Food food){
this.food = food;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(i % 2 == 0){ //生产食物
food.setFood("红烧肉","油而不腻");
}else{
food.setFood("糖醋鱼","甜而不腻");
}
}
}
}
Customer.java(消费者:服务员)
package com.lemon.servers;
/**
* 消费者:服务员
* @author lemonsun
*/
public class Customer implements Runnable{
private Food food;
public Customer(Food food){
this.food = food;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
food.getFood(); //消费食物
}
}
}
测试:
package com.lemon.servers;
/**
* 两个线程协同工作,先生产,再消费
* 面试题:
* sleep与wait的区别:
* sleep:让线程进入休眠状态,让出CPU的时间片,不释放对象监视器的所有权(对象锁)
* wait:让线程进入等待状态,让出CPU的时间片,并释放对象监视器的所有权,等待其他线程通过notify方法来唤醒
* @author lemonsun
*/
public class ProducterCustomerDemo {
public static void main(String[] args) {
Food food = new Food();
Producter p = new Producter(food);
Customer c = new Customer(food);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}