线程之生产者消费者案例-送奶
发布日期:2024-04-25 21:49:10 浏览次数:1 分类:技术文章

本文共 3555 字,大约阅读时间需要 11 分钟。

生产者和消费者问题是线程模型中的经典问题,生产者和消费者在同一时间段共用同一个存储空间,这个存储空间是一个缓冲区的仓库,生产者可以将产品放入仓库,消费者可以从仓库中取出产品。生产者/消费者模型是基于等待/通知机制,主要关注以下几点:生产者生产的时候消费者不能消费消费者消费的时候生产者不能生产缓冲区空时消费者不能消费缓冲区满时生产者不能生产主要优点:解耦。因为多了一个缓冲区,所以生产者和消费者并不直接相互调用,这一点很容易想到,这样生产者和消费者的代码发生变化,都不会对对方产生影响,这样其实就把生产者和消费者之间的强耦合解开,变为了生产者和缓冲区/消费者和缓冲区之间的弱耦合通过平衡生产者和消费者的处理能力来提高整体处理数据的速度,这是生产者/消费者模型最重要的一个优点。如果消费者直接从生产者这里拿数据,如果生产者生产的速度很慢,但消费者消费的速度很快,那消费者就得占用CPU的时间片白白等在那边。有了生产者/消费者模型,生产者和消费者就是两个独立的并发体,生产者把生产出来的数据往缓冲区一丢就好了,不必管消费者;消费者也是,从缓冲区去拿数据就好了,也不必管生产者,缓冲区满了就不生产,缓冲区空了就不消费,使生产者/消费者的处理能力达到一个动态的平衡。生产者消费者案例:    1.奶箱类(Box):定义一个成员变量,表示第x瓶奶,提供存储和获取牛奶的操作    2.生产者(Producer):实现Runnable接口,重写run()方法,调用存储牛奶的操作    3.消费者(Customer):实现Runnable接口,重写run()方法,调用存储牛奶的操作    4.测试类(SendMilkDemo):里面有main方法,main方法中的代码步骤如下:        a.创建奶箱对象,把奶箱作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作        b.创建生产者对象,把奶箱作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作        c.创建消费者对象,把奶箱作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作        d.创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递这里使用了wait()等待 和 notify()唤醒 方法。测试类:
package Mymodifier.testcode.src.Thread;public class SendMilkDemo{    public static void main(String[] strings)    {/*    生产者消费者案例:        1.奶箱类(Box):定义一个成员变量,表示第x瓶奶,提供存储和获取牛奶的操作        2.生产者(Producer):实现Runnable接口,重写run()方法,调用存储牛奶的操作        3.消费者(Customer):实现Runnable接口,重写run()方法,调用存储牛奶的操作        4.测试类(SendMilkDemo):里面有main方法,main方法中的代码步骤如下:            a.创建奶箱对象,把奶箱作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作            b.创建生产者对象,把奶箱作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作            c.创建消费者对象,把奶箱作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作            d.创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递*/        //创建奶箱对象,把奶箱作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作        Box b = new Box();        //创建生产者对象,把奶箱作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作        Producer p = new Producer(b);        //创建消费者对象,把奶箱作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作        Comsumer c = new Comsumer(b);        //创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递        Thread p2 = new Thread(p,"生产者");        Thread c2 = new Thread(c,"消费者");        //启动线程        p2.start();        c2.start();    }}

奶箱类:

package Mymodifier.testcode.src.Thread;public class Box{    //定义一个成员变量,表示第x瓶奶    private int milk;    //创建牛奶状态(默认为false)    private boolean state = false;    //存储牛奶数量(加了同步关键字才能使用wait(等待)和notify/All(唤醒))    public synchronized void put(int milk) {        //如果牛奶状态为true        if(state)        {            //则进入等待            try {                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        this.milk = milk;        //如果有牛奶,就消费牛奶        System.out.println("送奶工将第" + this.milk + "瓶放入奶箱");        //牛奶状态设置为true        state = true;        //唤醒全部等待线程        notifyAll();    }    //获取牛奶数量    public synchronized void get() {        //如果牛奶状态为false        if (!state)        {            //则进入等待            try {                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        //如果没有牛奶,就生产牛奶        System.out.println("用户拿到第" + this.milk + "瓶奶");        //牛奶状态设置为true        state = false;        //唤醒全部等待线程        notifyAll();    }}

生产者类(送奶工):

package Mymodifier.testcode.src.Thread;public class Producer implements Runnable{    private Box b;    public Producer(Box b)    {        this.b = b;    }    @Override    public void run() {        for(int i = 1; i < 6; i++)        {            b.put(i);        }    }}

消费者类:

package Mymodifier.testcode.src.Thread;public class Comsumer implements Runnable {    private Box b;    public Comsumer(Box b)    {        this.b = b;    }    @Override    public void run()    {        while(true)        {            b.get();        }    }}

转载地址:https://blog.csdn.net/FxShadow/article/details/124217612 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:线程之相关知识点总结
下一篇:线程之概述

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年05月02日 20时57分41秒