多线程与并发之生产者与消费者示例

版权声明:LemonSnm https://blog.csdn.net/LemonSnm/article/details/90109667

多线程开发经典操作案例,生产者-消费者,生产者不断生产产品,消费者不断取走产品

案例场景:

 饭店里有一个厨师和一个服务员,这个服务员必须等待厨师准备菜。当厨师准备好时,他会通知服务员。之后服务员上菜,然后返回继续等待。这是一个任务协作的示例,厨师代表生产者,服务员代表消费者。

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();
        

    }

    
}

猜你喜欢

转载自blog.csdn.net/LemonSnm/article/details/90109667