生产者与消费者问题

摘要:
生产者-消费者问题是Java多线程中的一个非常经典的问题。问题如下:生产者-消费者问题也称为缓存问题。生产者-消费者问题是Java中的线程。生产者-消费者问题是生产者生产的一定数量的线程被放入缓存中供消费者消费。在消费和生产过程中,如果生产者生产的产品超过缓冲区的上限,则停止生产,等待消费者消费。如果缓冲区内的产品被消费,消费者就会停止消费,等待生产者生产。首先,让我们看看这个话题。我们可以从主题中提取一个

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

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

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

生产者与消费者问题第1张

产品类

packageProducersAndConsumers;


//产品
public classProduct {

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


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


    publicInteger getProductId() {
        returnproductId;
    }


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

仓库

packageProducersAndConsumers;

importjava.util.LinkedList;
//仓库类
public classWareHouse {

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

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


    //生产方法
    public synchronized voidpush(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 voidpop() {
        //判断是否有产品
        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();
    }
}

生产者

packageProducersAndConsumers;
//生产者
public class Producer implementsRunnable {

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

    //仓库
    privateWareHouse wareHouse;

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

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

消费者

packageProducersAndConsumers;

public class Consumer implementsRunnable{

    //仓库
    privateWareHouse wareHouse;


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

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

最后测试类

packageProducersAndConsumers;
//测试类
public classMain {

    public static voidmain(String[] args) {

        WareHouse wareHouse = newWareHouse();

        Producer producer = newProducer(wareHouse);
        Consumer consumer = newConsumer(wareHouse);

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

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

    }
}

免责声明:文章转载自《生产者与消费者问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SaaS应用十大关键NFR【从零开始学SpringMVC笔记】SpringMVC进阶下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

java多线程:jdk并发包的总结(转载)

转载地址:http://blog.csdn.net/yangbutao/article/details/8479520 1、java 高并发包所采用的几个机制(CAS,volatile,抽象队列同步)    CAS(乐观操作),jdk5以前采用synchronized,对共享区域进行同步操作,synchronized是重的操作,在高并发情况下,会引起线程...

多线程之旅六——异步编程模式,自己实现IAsyncResult

作为模式,只是一种大家认可的经验,模式可以作为大家交流的词汇而存在。下面我们就要介绍几种异步编程模式,AMP、EAP和TAP。当然,法无定法,在我们理解的基础上,我们可以根据具体情况适度修改。下面介绍的只是在通常情况下的两种模式会是以什么样子的形式出现。   一 模型简介 1.APM 异步编程模型 这种模式的特征是一些成对出现的方法,分别以Begin和En...

mysql主从之多线程复制

多线程复制 mysql 主从复制原理: 1. master 节点上的binlogdump 线程,在slave 与其正常连接的情况下,将binlog 发送到slave 上。 2. slave 节点的I/O Thread ,通过读取master 节点binlog 日志名称以及偏移量信息将其拷贝到本地relay log 日志文件。 3. slave 节点的SQL...

当析构函数遇到多线程 ── C++ 中线程安全的对象回调

陈硕 (giantchen_AT_gmail) 本文 PDF  下载: http://www.cppblog.com/Files/Solstice/dtor_meets_mt.pdf 摘要 编写线程安全的类不是难事,用同步原语保护内部状态即可。但是对象的生与死不能由对象自身拥有的互斥器来保护。如何保证即将析构对象 x 的时候,不会有另一个线程正在调用...

Python 并发总结,多线程,多进程,异步IO

1 测量函数运行时间 importtime defprofile(func): def wrapper(*args, **kwargs): importtime start =time.time() func(*args, **kwargs) end =time.time()...

python GIL 全局锁,多核cpu下的多线程性能究竟如何?

python GIL 全局锁,多核cpu下的多线程性能究竟如何?GIL全称Global Interpreter Lock GIL是什么? 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,...