Java线程同步实例 生产者 消费者问题分析

Java线程同步实例 生产者 消费者问题分析

  • 实例
    生产者消费者问题:
package thread.wait.notify;

public class Test1 {
    public static void main(String []args) {
         SynStack synStack=new SynStack();
         Producer producer=new Producer(synStack);
         Consumer consumer=new Consumer(synStack);
         new Thread(producer, "producer").start();
         new Thread(consumer,"consumer").start();
    }
}
class Wotou{
    int id;
    Wotou(int id ){
        this.id=id;
    }
}
class Producer implements Runnable{
    SynStack synStack;
    public Producer(SynStack synStack) {
        this.synStack=synStack;
    }
    public void run(){
        System.out.println("producer开始生产馒头");
        for(int i=1;i<=20;i++){
            Wotou wotou=new Wotou(i);
            synStack.push(wotou);
            System.out.println("producer生产馒头"+wotou.id);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Consumer implements Runnable {
    SynStack synStack;
    public Consumer(SynStack synStack) {
        this.synStack=synStack;
    }
    public void run(){
        System.out.println("consumer开始吃馒头");
        for(int i=1;i<=20;i++){
            Wotou w=synStack.pop();
            System.out.println("consumer吃馒头"+w.id);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class SynStack{
    int index=0;
    Wotou [] wotous=new Wotou[10];
    synchronized void  push(Wotou wotou){
        if(index==wotous.length){
            try {
                System.out.println("当前有"+index+"个馒头,吃了后才能生产,等待吃。。。");
                wait();
                System.out.println("当前有"+index+"个馒头,等待结束。。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        notify();
        wotous[index]=wotou;
        index++;
    }
    synchronized Wotou pop(){
        if(index==0){
            try {
                System.out.println("当前有"+index+"个馒头,生产后了才能吃,等待生产。。。");
                wait();
                System.out.println("当前有"+index+"个馒头,生产完毕。。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        notify();
        index--;
        return wotous[index];
    }
}

把main函数改为下面代码,即增加2个消费者:

    public static void main(String []args) {
         SynStack synStack=new SynStack();
         Producer producer=new Producer(synStack);
         Consumer consumer=new Consumer(synStack);
         new Thread(producer, "producer").start();
         new Thread(consumer,"consumer").start();
         Consumer consumer2=new Consumer(synStack);
         Consumer consumer3=new Consumer(synStack);
         new Thread(consumer2,"consumer2").start();
         new Thread(consumer3,"consumer3").start();
    }

运行之后发现会报下面的错误:
这里写图片描述
报错原因:当producer生产第一个馒头之前,馒头数为0,consumer,consumer2,consumer3都在wait,当producer生产了第一个馒头,会执行一次notify,在这个例子notify了consumer3的wait,所以 consumer3吃了馒头,consumer3吃完后,又会执行notify,而此时wait的包括了consumer,consumer2,因为馒头为0,notify他们其中之一后,馒头为-1,当然会报错。改进方法:把pop函数的if改为while即可,如果当前馒头为0,则再进入wait状态:

    synchronized Wotou pop(){
        while(index==0){
            try {
                System.out.println(Thread.currentThread().getName()+" 当前有"+index+"个馒头,生产后了才能吃,等待生产。。。");
                wait();
                System.out.println(Thread.currentThread().getName()+" 当前有"+index+"个馒头,生产完毕。。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        notify();
        index--;
        return wotous[index];
    }

同理,如果有很多生产者,也需要把push中if改为while。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值