问题描述
生产者消费者问题(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 条评论) “” |