这是一个面试经常被问到的问题,很多问题都可以转化为这个模型。
什么是生产者与消费者问题?举个例子,我们去吃自助餐,在自助餐的一个公共区域放着各种食物,消费者需要就自行挑选,当食物被挑没的时候,大家就等待,等候厨师做出更多再放到公共区域内供大家挑选;当公共区域食物达到一定数量,不能再存放的时候,此时没有消费者挑选,厨师此时等待,等公共区域有地方再存放食物时,再开始生产。这就是一个生产者与消费者问题。
根据这个例子,我们可以模拟一下场景,我们从这个例子中,显然看出我们需要制造一个公共区域,而且这个公共区域是有容量限制的,需要模拟各种食物,同时还需要模拟几个厨师也就是生产者,最后再模拟几个消费者。
首先呢,我们创建一个产品Product类,这个类就代表食物的模板,厨师们就生产这种类型的食物,类里面定义食物的ID和name这两个属性,代码如下:
public class Product { private int id; private String name; public Product(int id, String name) { super(); this.id = id; this.name = name; } @Override public String toString() { return "Product :id:"+id+",name:"+name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
接下来,我们创建那个公共区域,也就是一个容器,容器要么用数组保存,要么用集合,这里我们用集合LinkedList,然后呢,我们要清楚我们这个容器只能被创建一个,也就是公共区域只有一个,我们放也是放在这里面,取也是从这里面取,这里采用单例模式来保证只能创建一个容器实例,容器里面再定义放和取的方法,我们要加锁保证放和取的同步,以免发生线程安全问题,同时还要定义容器的最大容量,再放和取的同步方法里面,我们要判断是否容器内的食物超出了容器的最大容量,如果放的时候大于等于最大容量了,就不能再往里面放了,这时候厨师们(生产者)要等待;取的时候也一样,看是否容器内的食物个数为0,为0消费者们就要等待,最后我们在容器里面定义一个检查容器容量的方法,后面单独开启一个线程调用此方法,实时监测容器内食物的个数,一直在0-10之间,就说明我们写的代码没有问题,代码如下:
public class Container { //单例模式,保证只能创建一个容器实例 private static Container instance = null; private Container(){} public static Container getInstance(){ if(instance == null){ instance = new Container(); } return instance; } private LinkedList<Product> list = new LinkedList<>();//容器 private int MAX = 10;//容器的最大容量 //放食物 public synchronized void putProduct(Product product){ while(li

