生产者--消费者模式

生产者–消费者模式

生产者--消费者模式是使用多线程的典型操作案例,每生产一个对象消费者就取走一个对象,生产者不断生产对象,消费者不断消费对象

想要实现生产者--消费者模式,是要使用到synchronized(同步)以及Object对象的wait()notify()/notifyAll()方法
    使用synchronized是为了防止值错乱;
    使用wait()notify()/notifyAll()是为了解决值重复的问题
   	看以下代码:
//Food类
package threaddemo;
public class Food {
    private String name;
    private float price;
    //如果为false则表示要生产、如果为true则表示要消费
    private boolean flag = false;
    public Food() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
    public void  set(String name,float price) throws InterruptedException {
        //使用同步锁
        synchronized (this){
            if(flag){
                //如果为true,则不能生产,释放锁标志
                this.wait();
            }
            this.setName(name);
            Thread.sleep(300);
            this.setPrice(price);

            this.flag = true;
            this.notify();//唤醒其他线程,重新抢CUP
        }
    }
    public void get() throws InterruptedException {
        synchronized(this){
            if(!flag){
                //如果为false,则不能消费,释放锁标志
                this.wait();
            }
            System.out.println(this.name+"--->"+this.price);
            Thread.sleep(300);
            this.flag = false;
            this.notify();//唤醒其他线程,重新抢CUP
        }
    }
}
//Consumer消费者类
package threaddemo;
public class Consumer implements Runnable {
    private Food food;
    Consumer(Food food){
        this.food = food;
    }
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            try {
                food.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//生产者类
package threaddemo;

public class Producter implements Runnable {
    private Food food;
    Producter(Food food){
        this.food = food;
    }
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            if(i%2==0){
                try {
                    food.set("糖醋排骨",45.0f);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                try {
                    food.set("清蒸山药", 38.0f);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
//Test测试类
package threaddemo;
public class Test {
    public static void main(String[] args) {
        Food food  = new Food();
        //创建生产者实例
        Producter producter = new Producter(food);
        //创建消费者实例
        Consumer consumer = new Consumer(food);
        //启动生产者和消费者线程
        new Thread(producter).start();
        new Thread(consumer).start();
    }
}

在以上代码中,我们实现的是一个厨师炒菜以及客户吃菜的一个生产者--消费者实例,在上述中:
 	解决值错乱的问题是在Food类使用synchronized代码块将setName和setPrice放在一个锁里面。这样无论是那个线程抢到了CUP,这个线程中run方法里面的set方法会完整的执行,不会中途因为阻塞而产生值错乱。
    解决重复取值的问题是使用wait、notify和flag(改变状态的变量)来解决的。首先看一下方法的用法(这三个方法必须在synchronized函数或者synchronized block中进行调用)
    wait()后,线程会释放它所占有的“锁标志”,从而是线程所在的对象中的其他synchronized数据可以被别的线程使用。
    notify()会唤醒第一个等待的线程。
    notifyAll()唤醒全部等待的线程,那个优先级高,就先执行那个
 	然后在以上的操作中应该增加一个标志位,此标志位应有两种状态,可以使用boolean类型来表示:
    1. 如果boolean的值是false的话表示可以生产,不能取走
    2. 如果boolean的值是true的话表示可以取走,不能生产
然后在以上的操作中应该增加一个标志位,此标志位应有两种状态,可以使用boolean类型来表示:
    1. 如果boolean的值是false的话表示可以生产,不能取走
    2. 如果boolean的值是true的话表示可以取走,不能生产
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值