Java线程生产者消费者问题详解

问题描述

生产者消费者问题(Producer-consumer problem),也称有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例。生产者生成一定量的数据放到缓冲区中,然后重复此过程;与此同时,消费者也在缓冲区消耗这些数据。生产者和消费者之间必须保持同步,要保证生产者不会在缓冲区满时放入数据,消费者也不会在缓冲区空时消耗数据。不够完善的解决方法容易出现死锁的情况,此时进程都在等待唤醒。

先举个例子:

卖家:汽车厂商 买家:张三

张三想买一辆五菱宏光 , 告知汽车厂商我要买车。张三会进入等待状态,等到五菱厂家造完以后,再通知张启来提车。如果五菱厂家有现车,张启就直接提车。

如果产品需要生产的话,消费者进入到阻塞状态。

如果产品不需要生产的话,消费者直接购买。

解决方法

采用某种机制保护生产者和消费者之间的同步。有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式。

在生产者和消费者之间建立一个管道。管道缓冲区不易控制,被传输数据对象不易于封装等,实用性不强。

保证同一资源被多个线程并发访问时的完整性。常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。

图解:

代码实现:

仓库类

//为啥要写这个类?这个类是作为两个线程之间通信的桥梁class Goods {    private String name;//名字    private double price;//价格    private boolean isProduct;//是否有这个商品, true 需要生产    //false   不需要生产商品    public Goods(String name, double price, boolean isProduct) {        this.name = name;        this.price = price;        this.isProduct = isProduct;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public double getPrice() {        return price;    }    public void setPrice(double price) {        this.price = price;    }    public boolean isProduct() {        return isProduct;    }    public void setProduct(boolean product) {        isProduct = product;    }   }

消费者

//消费者线程class Customer implements Runnable {    private Goods goods;    public Customer(Goods goods) {        this.goods = goods;    }    @Override    public void run() {        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        while (true) {            synchronized (goods) {                //一直消费                //goods.isProduct()  true  需要生产 没有商品                //false  不需要生产的                if (!goods.isProduct()) {                    System.out.println("消费者购买了:" + goods.getName() + ",价格为:" + goods.getPrice());                    //购买完以后 商品没了  isProduct 是true  没有商品了                    goods.setProduct(true);                    //唤醒生产者去生产                    goods.notify();                } else {                    //需要生产  消费者进入阻塞                    try {                        goods.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }    }}

生产者

//生产者线程class Productor implements Runnable {    private Goods goods;    public Productor(Goods goods) {        this.goods = goods;    }    @Override    public void run() {        int count = 0 ;        while (true) {//一直生产商品            synchronized (goods) {                if (goods.isProduct()) {//true  需要生产者                    //造车,奇数造一种车, 偶数的话造另外一种车                    if (count % 2 == 0) {//偶数                        goods.setName("玛莎拉蒂");                        goods.setPrice(200);                    } else {                        goods.setName("五菱宏光");                        goods.setPrice(400);                    }                    //生产完以后一定要记得 将标记改false                    goods.setProduct(false);                    System.out.println("生产者生产了:" + goods.getName() + ",价格为:" + goods.getPrice());                    count++;                    //生产者完了以后,人家消费者在等待这你呢                    //唤醒消费者                    goods.notify();                } else {                    //不需要生产车,你就等着就行                    try {                        goods.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }    }}

测试类

public class Demo2 {    public static void main(String[] args) {        Goods goods = new Goods("东风", 89, false);        //false不需要生产的  谁阻塞 生产者阻塞        //最好是让生产者线程先执行        Productor productor = new Productor(goods);        new Thread(productor).start();        Customer customer = new Customer(goods);        new Thread(customer).start();        /**         * 消费者购买了:东风,价格为:89.0         * 生产者生产了:玛莎拉蒂,价格为:200.0         * 消费者购买了:玛莎拉蒂,价格为:200.0         * 生产者生产了:五菱宏光,价格为:400.0         * 消费者购买了:五菱宏光,价格为:400.0         * 生产者生产了:玛莎拉蒂,价格为:200.0         * isProduct = false         * 走了else  代码是生产者阻塞了 消费在睡了一秒之后立马执行         * 看消费者   有商品 买走了,之后   isProduct=true         * 唤醒生产者了,         * 生产者生产了:玛莎拉蒂,价格为:200.0  isProduct=false         *         */    }}
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章