Java线程间的通信——消费者和生产者模型

一、生产者消费者模型

该模型是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

二、单线程之生产者与消费者

单线程模式:生产者生产商品时,消费者不能消费商品;反之,消费者消费商品时,生产者不能生产商品,即进程在执行时一次只能有线程。
这里我们设置缓冲区的容量为1(缓冲区中存放数据)。

1.商品类

商品类中定义了生产商品和消费商品的方法
(生产、消费商品是商品的属性行为,所以我们定义在商品类中,同时这样也可以直接对商品的成员变量进行操作)

package SingleProducerConsumer;

/*单线程模式:生产者生产商品时,消费者不能消费商品,反之亦然
所以货架上最多有一个商品
* */

public class Goods {
    private String goodsName;
    private int count;//count为线程执行对应操作前的库存量

    @Override
    public String toString() {
        return "Goods{" +
                "goodsName='" + goodsName + '\'' +
                ", count=" + count +
                '}';
    }

    //生产商品
    public synchronized void set(String goodsName) {
        //先进行判断,再执行相应操作
        if(count>0){
            System.out.println("商品还有库存,等会再生产!");
            try {
                //某些条件没有被满足,调用wait方法暂停自己的执行
                this.wait();//暂停生产者的执行,等待消费者消费
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.goodsName=goodsName;
        System.out.println(Thread.currentThread().getName()+"生产"+toString());
        count++;
        notify();
    }

    //消费商品
    public synchronized void get() {
        //先进行判断,再执行相应操作
        if(count<0){
            System.out.println("商品没有库存,等会再消费!");
            try {
                this.wait();//暂停生产者的执行,等待消费者消费
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"消费"+toString());
        count--;
        notify();//唤醒生产者继续生产线程
    }
}

2.生产者类

package SingleProducerConsumer;

public class Producer implements Runnable {
    private Goods goods;

    public Producer(Goods goods) {
        this.goods = goods;
    }

    //生产者生产商品
    public void run() {
        goods.set("蛋黄酥");
    }
}

3.消费者类

package SingleProducerConsumer;

public class Consumer implements Runnable{
    Goods goods;

    public Consumer(Goods goods) {
        this.goods = goods;
    }

    //消费者消费商品
    public void run() {
        goods.get();
    }

}

4.测试类

package SingleProducerConsumer;

public class Test {
    public static void main(String[] args) throws InterruptedException {
        //传递一个商品,注意:生产者和消费者必须对同一个商品进行处理
        Goods goods = new Goods();

        Producer producer = new Producer(goods);
        Consumer consumer = new Consumer(goods);
        Thread producerThread= new Thread(producer, "生产者线程");
        Thread consumerThread= new Thread(consumer, "消费者线程");

        producerThread.start();
        //当前主线程休眠1秒
        Thread.sleep(1000);
        consumerThread.start();
    }
}

5.注意事项

1.生产者线程和消费者线程必须对同一个商品类进行处理,所以在类Producer,Consumer中传入商品类时,不能写成Goods goods=new Goods()
2.wait方法需要被try-catch包含
3.wait/notify/notifyAll都必须包裹在同步代码块/同步方法中
4.同步代码块/同步方法的最后不要掉了notify/notifyAll方法

三、个人感悟

果然实践是检验真理的唯一标准,这个单线程的模型我以为我懂了,结果敲代码时各种错误以及发现了很多需要注意的点,所以还是要动手!!!

四、多线程之生产者与消费者

这里先挖一个坑,以后再填

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值