生产者与消费者问题

生产者与消费者问题是Java多线程中一道非常经典的问题,问题如下:

  生产者与消费者问题也称缓存问题,生产者与消费者即Java 中的线程,生产者与消费者问题即生产者生产一定数量的线程放入缓存区中,供消费者消费者消费,在消费和生产的过程中,如果生产者生产的产品超过了缓存区的上限则停止生产,等待消费者消费,如果缓存区的产品被消费完,消费者则停止消费,等待生产者生产

   首先,我们来看题目,从题目中我们一个可以抽取出几个实体类呢?答案是4个 Consumer(消费者),Producer(生产者),Product(产品),WareHouse(缓冲区,也叫仓库),于是项目结构如下,main 为测试类

生产者与消费者问题

产品类

package ProducersAndConsumers;


//产品
public class Product {

    //产品需要一个id 来表明产品的唯一性
    private Integer productId;


    //id直接由构造方法传入
    public Product(Integer productId) {
        this.productId = productId;
    }


    public Integer getProductId() {
        return productId;
    }


    @Override
    public String toString() {
        return "Product{" +
                "productId=" + productId +
                '}';
    }
}

 

仓库

package ProducersAndConsumers;

import java.util.LinkedList;
//仓库类
public class WareHouse {

    //仓库容量,我们设置为10个
    private final int max = 10;
    //仓库基础的数量
    private final int base = 0;

//我们设置一个集合来存放生产的产品,由于我们需要一个可以弹出最后一个产品的方法,所以我们在这里使用LinkedList
    private LinkedList<Product> products = new LinkedList<>();


    //生产方法
    public synchronized void push(Product product) {
        //判断是否有空间存放产品
        while(max==products.size()){
            try{
                System.out.println("仓库已满,消费者快来消费"+Thread.currentThread().getName()+"停止生产");
                //仓库满后停止当前线程
                this.wait();
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
        //生产商品
        products.addLast(product);
        System.out.println(Thread.currentThread().getName()+"生产了一个产品:"+product.getProductId()+"号");
        try{
            //等待1秒,方面我们观察
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        notifyAll();

    }
//消费方法
    public synchronized void pop() {
        //判断是否有产品
        while (products.size()==base){
            try{
                System.out.println("仓库空了,生产者快点生产"+Thread.currentThread().getName()+"停止消费");
                //仓库空后停止当前线程
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //消费商品
        System.out.println(Thread.currentThread().getName()+"消费了一个产品:"+products.getLast().getProductId()+"号");
        products.removeLast();
        try{
            //等待1秒,方面我们观察
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        notifyAll();
    }
}

生产者

package ProducersAndConsumers;
//生产者
public class Producer implements Runnable {

    //生产产品的id
    private int count = 0;

    //仓库
    private WareHouse wareHouse;

    //生产者和消费者都是用同一个仓库,所以我们只要声明一个仓库,在由构造方法传入即可
    public Producer(WareHouse wareHouse) {
        this.wareHouse = wareHouse;
    }

    //生产方法
    @Override
    public void run() {
        while (true){
            Product product = new Product(count);
            wareHouse.push(product);
//            产品id不可重复,所以我们使用自增策略
            count++;
        }
    }
}

消费者

package ProducersAndConsumers;

public class Consumer implements Runnable{

    //仓库
    private WareHouse wareHouse;


    //生产者和消费者都是用同一个仓库,所以我们只要声明一个仓库,在由构造方法传入即可
    public Consumer(WareHouse wareHouse) {
        this.wareHouse = wareHouse;
    }

    //消费方法
    @Override
    public void run() {
        while (true){
            wareHouse.pop();
        }
    }
}

最后测试类

package ProducersAndConsumers;
//测试类
public class Main {

    public static void main(String[] args) {

        WareHouse wareHouse = new WareHouse();

        Producer producer = new Producer(wareHouse);
        Consumer consumer = new Consumer(wareHouse);

        Thread producerT = new Thread(producer,"生产者");
        Thread consumerT = new Thread(consumer,"消费者");

        producerT.start();
        consumerT.start();

    }
}

 

上一篇:NTLM协议与Pass the Hash的爱情


下一篇:hive的基础理论