生产者消费者问题JAVA版

1、引言

生产者消费者是一个古老而又经典的问题,虽然现在已经有很多成熟的解决方案,但是里面的思想仍然值得我们去学习,去思考。

主要是在高并发场景下,我们是如何保证生产者在生产商品的时候是顺序向仓库里面添加商品的,什么时候仓库商品已满,停止生产商品,消费者是如何进行消费商品的,在什么条件下才能去消费商品,以及每次消费商品的数量能否保证,今天,我们就来讲讲如何实现一个较为完美的解决方案,

2、解决方案

思想:生产者每次生产商品都默认把商品放进仓库,当仓库满时则停止生产,进入等待状态,等待消费者消费商品,如果没有满,则在生产完商品时通知消费者去消费。消费者每次消费商品都默认从仓库中去取,判断仓库中是否有足够的库存容量,如果有,就进行取出消费,如果没有,就进行等待,知道生产者生产完产品发出通知。好了,前面就是我们大概的思路,我们现在把生产者,消费者、仓库三个类提取出来,开始编写我们的代码了。

1、消费者代码

package conditionTestManyToMany;

/**
 * 消费者类继承线程类thread
 */
public class Consumer extends Thread{
    //每次消费的产品数量
    private int num;

    //仓库
    private Storage storage;

    //构造函数,设置仓库
    public Consumer(Storage storage){
        this.storage = storage;
    }
    //线程函数
    @Override
    public void run(){
        consume(num);
    }
    public void consume(int num){
        storage.consume(num);
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public Storage getStorage() {
        return storage;
    }

    public void setStorage(Storage storage) {
        this.storage = storage;
    }
}

 2、生产者代码

package conditionTestManyToMany;

/**
 * 生产者类继承线程类Thread
 * @author Archer
 */
public class Producer extends Thread{
    //每次生产的产品数量
    private int num;

    //所在放置的仓库
    private Storage storage;

    public Producer(Storage storage){
        this.storage = storage;
    }

    //线程函数
    @Override
    public void run(){
        produce(num);
    }

    //调用仓库的Storage的生产函数
    public void produce(int num){
        storage.produce(num);
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public Storage getStorage() {
        return storage;
    }

    public void setStorage(Storage storage) {
        this.storage = storage;
    }
}

 3、仓库代码

package conditionTestManyToMany;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Storage {
    //仓库最大容量
    private final int MAX_SIZE = 100;

    //仓库存储的载体
    private LinkedList<Object> list = new LinkedList<>();

    //锁
    private final Lock lock = new ReentrantLock();

    //仓库满的条件变量
    private final Condition full = lock.newCondition();

    //仓库空的条件变量
    private final Condition empty = lock.newCondition();

    //生产num个产品
    public void produce(int num){
        //获得锁
        lock.lock();
        //仓库已满,等待消费者消费
        while(list.size() + num > MAX_SIZE){
            System.out.println("【要生产的产品数量】:" + num + "/t【库存量】:" + list.size()
                    + "/t暂时不能执行生产任务!");
            try{
                full.await();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        //生产num个产品
        for(int i = 0;i < num;i++){
            list.add(new Object());
        }
        System.out.println("【已经生产产品数】:" + num + "/t【现仓储量为】:" + list.size());
        full.signalAll();
        empty.signalAll();
        lock.unlock();
    }

    public void consume(int num){
        lock.lock();
        //如果库存数量少于消费的产品数量,则进行等待
        while(list.size() < num){
            System.out.println("【要消费的产品数量】:" + num + "/t【库存量】:" + list.size()
                    + "/t暂时不能执行生产任务!");
            try{
                empty.await();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        //消费条件满足的情况下消费num个产品
        for(int i = 0;i < num;i++){
            list.remove();
        }
        System.out.println("【已经消费产品数】:" + num + "/t【现仓储量为】:" + list.size());
        full.signalAll();
        empty.signalAll();
        lock.unlock();
    }

    public LinkedList<Object> getList() {
        return list;
    }

    public void setList(LinkedList<Object> list) {
        this.list = list;
    }

    public Lock getLock() {
        return lock;
    }

    public int getMAX_SIZE() {
        return MAX_SIZE;
    }
}

4、测试类 

package conditionTestManyToMany;

public class Test {
    public static void main(String[] args) {
        //仓库对象
        Storage storage = new Storage();

        //生产者对象
        Producer p1 = new Producer(storage);
        Producer p2 = new Producer(storage);
        Producer p3 = new Producer(storage);
        Producer p4 = new Producer(storage);
        Producer p5 = new Producer(storage);
        p1.setNum(10);
        p2.setNum(15);
        p3.setNum(5);
        p4.setNum(20);
        p5.setNum(90);
        Consumer c1 = new Consumer(storage);
        Consumer c2 = new Consumer(storage);
        Consumer c3 = new Consumer(storage);
        c1.setNum(20);
        c2.setNum(30);
        c3.setNum(50);
        p1.start();
        p2.start();
        p3.start();
        p4.start();
        p5.start();
        c1.start();
        c2.start();
        c3.start();
    }
}

5、结果

【已经生产产品数】:10/t【现仓储量为】:10
【已经生产产品数】:15/t【现仓储量为】:25
【已经生产产品数】:5/t【现仓储量为】:30
【已经生产产品数】:20/t【现仓储量为】:50
【要生产的产品数量】:90/t【库存量】:50/t暂时不能执行生产任务!
【已经消费产品数】:20/t【现仓储量为】:30
【要生产的产品数量】:90/t【库存量】:30/t暂时不能执行生产任务!
【已经消费产品数】:30/t【现仓储量为】:0
【已经生产产品数】:90/t【现仓储量为】:90
【已经消费产品数】:50/t【现仓储量为】:40

Process finished with exit code 0

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值