Java多线程与并发(五)之生产者与消费者案例

生产者与消费者应用案例

多线程的开发中有一个经典的操作案例,就是生产者-消费者,生产者不断生产产品,消费者不断取走产品。
例如: 饭店里的有一个厨师和一个服务员,这个服务员必须等待厨师准备好膳食。当厨师准备好时,他会通知服务员,之后服务员上菜,然后返回继续等待。这是一个任务写作的示例,厨师代表生产者,而服务员代表消费者。

首先我们需要创建相应的类:
生产者类, 用于生产产品(我们这里的产品指的是Food,该类在下面展示)
假设我们生产的食物有两种”重庆小面”和”糖醋里脊”,

// 生产者类
class Producter implements Runnable {

    private Food food;

    public Producter(Food food) {
        this.food = food;
    }

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            if (i % 2 == 0) {
                food.set("重庆小面", "就是好吃!!!");
            } else {
                // 是奇数的时候
                food.set("糖醋里脊", "酸甜可口!");
            }
        }
    }

}

消费者类,也就是消费食物

// 消费者类
class Customer implements Runnable {
    private Food food;

    public Customer(Food food) {
        this.food = food;
    }

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            food.get();

        }
    }
}

消费和生产的对象, 食物类,这是我们的核心类, 同步代码在该类中体现.

注:在这里就用到了我在之前博客中提到的wait()方法和notify()方法,简单说明一下:
1. wait方法表示当前线程进入等待状态,会让出CPU并释放该监视器上的锁,但是要注意跟sleep方法的区别,sleep方法执行后是不会让出锁的,代码中执行了wait方法后会一直等待被“唤醒”, 也就是notify方法
2. notify方法, 用来唤醒已等待的方法,还有一个notifyAll方法,区别在于前者只唤醒其中一个,而后者则唤醒全部

// 消费的对象(数据), 食物类
class Food {
    private String name;//菜名
    private String efficacy;//功效
    // true表示可以生产 false表示可以消费
    private boolean flag = true;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEfficacy() {
        return efficacy;
    }

    public void setEfficacy(String efficacy) {
        this.efficacy = efficacy;
    }

    public Food(String name, String efficacy) {
        super();
        this.name = name;
        this.efficacy = efficacy;
    }

    // 生产产品
    public synchronized void set(String name, String efficacy) {
        // System.out.println("重庆小面");
        // 表示不能生产,但是可以消费,需要把时间让出啦
        if (!flag) {
            try {
                // 等待跟休眠不同,sleep会进入等待但是不会让出锁
                this.wait();// 表示当前线程进入等待状态,会让出CPU并释放该监视器上的锁
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        this.setName(name);

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        this.setEfficacy(efficacy);

        // 生产完成后
        flag = false;
        this.notify();// 唤醒该监视器上的其他线程(只是唤醒一个)

    }

    public synchronized void get() {

        if (flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println(this.getName() + "->" + this.getEfficacy());
        this.notify();
        flag = true;
    }
    public Food() {
    }
}

测试类

public class ThreadDemo4 {

    public static void main(String[] args) {
        Food food = new Food();
        Producter p = new Producter(food);
        Customer c = new Customer(food);

        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);

        t1.start();
        t2.start();
    }

}

代码执行结果:
这里写图片描述

以上纯属个人见解, 如有不足之处希望有高人指出, 定感激不尽, 如有喜欢交流学习经验请给我留言谢谢.

原创文章, 转载请注明出处

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值