Java多线程,生产者消费者问题

问题:

有一个生产者和一个消费者,和一个仓库。仓库容量为4,生产10次和消费10次


问题描述

程序多次运行出现不能正常退出现象:
在这里插入图片描述
问题代码:

//生产者
class Product extends Thread{
    private Store store;
    public Product(Store store) {
        this.store = store;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            store.produce();
        }
    }
}
//消费者
class Consumer extends Thread{
    private Store store;
    public Consumer(Store store) {
        this.store = store;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            store.consume();
        }
    }
}
//仓库
class Store{
    private int memory = 0;
    //生产方法
    public synchronized void produce(){
        if(memory < 4){
            memory ++;
            System.out.println("生产第" + memory + "产品");
            notify();
        }else{
            System.out.println("仓库产品已满,放不下,等待消费");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //消费方法
    public synchronized void consume(){
        if(memory > 0){
            System.out.println("消费第" + memory + "产品");
            memory--;
            notify();
        }else {
            System.out.println("仓库没有产品可以消费,等待生产");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//测试代码:
public static void main(String[] args) {
        Store store = new Store();
        Product product = new Product(store);
        Consumer consumer = new Consumer(store);
        product.setName("生产者");
        consumer.setName("消费者");
        product.start();
        consumer.start();
    }

原因分析:

在生产者和消费者中是循环生产和消费的,当进入仓库开始判断是否进行生产或消费时,如果此时仓库是满的或者空的,那么不进行生产或消费。但是在生产者和消费者的循环中是循环了一次的,从而导致生产者或消费者一方不能完整的进行10次生产或消费,在循环10次之后线程结束。而另一个线程没有循环10次,还在运行,如果仓库满了或仓库空了,则要wait(),但是此时另一个线程已经结束,无法进行生产和消费,所以会出现程序不能正常结束的现象。


解决方案:

方法1 :

可以将生产者和消费者中的循环改成while,仓库中的生产方法和消费方法根据是否进行生产返回一个boolean值,在生产者和消费者的循环中判断返回的boolean值,进而选择是否是一次有效的生产或者循环。真实的循环次数可能大于10,而真正进行生产和消费的次数为10次。代码如下:

//生产方法
    public synchronized boolean produce(){
        if(memory < 4){
            memory ++;
            System.out.println("生产第" + memory + "产品");
            notify();
            return true;
        }else{
            System.out.println("仓库产品已满,放不下,等待消费");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
  			return false;
        }
    }
//消费方法中修改方式相同


//生产者中的run方法
 @Override
    public void run() {
        while(count < 10) {
            if(store.produce()){
            	count++;
            }
        }
    }
//消费者中的run方法修改方式相同
方法2 :

wait()后的线程,再次被唤醒时会接着上次运行到的地方继续向下执行,所以可以在生产方法和消费方法中的判断语句由if改为while。这也是源码中写的示例:
在这里插入图片描述
修改后的代码如下:

//生产方法
    public synchronized void produce(){
        while(memory >= 4){
            System.out.println("仓库产品已满,放不下,等待消费");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        memory ++;
        System.out.println("生产第" + memory + "产品");
        notify();
    }
//消费方法中修改方式相同

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值