java简单做一个消费者/生产者案例

首先 我们创建一个包
在包下创建
四个类
首先是奶箱类 milkBox 在业务中充当数据的存储类
参考代码如下

public class milkBox {
    private int milk;
    public void put (int milk){
        this.milk = milk;
        System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");
    }
    public void get(){
        System.out.println("用户拿到第"+this.milk+"瓶奶");
    }
}

奶箱类 定义了一个milk公共变量 用于统计当前是第几瓶奶
提供了插入方法 put 可以改变milk的值
获取方法 get 可以实时获取当前是第几瓶奶

producer 生成者类 参考代码如下

public class producer implements Runnable {
    milkBox ma;
    public producer(milkBox ma) {
        this.ma = ma;
    }
    public void run (){
        for(int i = 1;i < 6;i++){
            ma.put(i);
        }
    }
}

这里 我们通过带参构造方法 获取了milkBox奶箱类的对象 并存储 实现了Runnable接口 可以实现线程

然后 run 方法中编写逻辑 循环调用5次奶箱类 put插入方法

消费者类 consumer 参考代码如下

public class consumer implements Runnable {
    milkBox ma;
    public consumer(milkBox ma) {
        this.ma = ma;
    }
    public void run (){
        while (true) {
            ma.get();
        }
    }
}

我们消费者类 也利用带参构造方法 获取了milkBox奶箱类的对象 也存储了起来 也实现了 Runnable 接口 说明要实现为一个线程

run 编写一个死循环 去获取 奶箱中的milk变量

text 测试类 参考代码如下

public class text {
    public static void main(String args[]) {
        milkBox ma = new milkBox();
        producer pre = new producer(ma);
        consumer cons = new consumer(ma);
        Thread p = new Thread(pre);
        Thread c = new Thread(cons);
        p.start();
        c.start();
    }
}

我们测试类 通过main 先实例化了 milkBox 奶箱类 然后实例化producer 生产者类 在实例化时 通过构造方法 将milkBox 奶箱类的对象传给了生产者类 下面对consumer消费者类的实例化也是同理

然后通过Thread将生产者 和 消费者类都实例化成了线程

最后调用 start 方法 启动线程

然后我们执行代码
因为 我们消费者类里写的是个死循环 所有 运行一段时间 要赶紧停掉
在这里插入图片描述
但把记录翻到最上面 好像用户一直在拿第五瓶奶
在这里插入图片描述
这是因为 生产者方法 执行的太快了

我们需要改造一下奶箱类里的两个数据处理方法

将 milkBox 类代码修改如下

public class milkBox {
    private int milk;
    private boolean stock;
    public synchronized void put (int milk){
        if(stock) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.milk = milk;
        System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");
        stock = true;
    }
    public synchronized void get(){
        if(!stock) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("用户拿到第"+this.milk+"瓶奶");
        stock = false;
    }
}

首先 我们定义了一个布尔类型的变量 stock 监听奶箱里还有没有牛奶没被消费

然后 把插入 put方法 改成同步方法 因为只有这样才能用锁 然后 判断 stock如果为true 所有还没没有被消费的牛奶 那么 他就等待

stock为 false 说明 已经没有没被消费过的牛奶了 这时 我们执行 插入奶数量逻辑 执行完之后 把stock赋值为 true 告诉系统 我们新加的牛奶还没被消费过

同时 get 消费方法也被上了锁 如果 stock为 false 所有 牛奶都被消费过 我们进入等待 然后

stock为true 说明 还有牛奶没被消费 这时我们执行消费牛奶逻辑 结束后将stock改为 false 说明 牛奶都被消费过了

然后我们运行代码 效果如下

在这里插入图片描述
但这时 显然卡死了 就执行了一次 因为我们暂时只有锁定 但没有唤醒操作

将 milkBox 代码更改如下

public class milkBox {
    private int milk;
    private boolean stock;
    public synchronized void put (int milk){
        if(stock) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.milk = milk;
        System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");
        stock = true;
        notifyAll();
    }
    public synchronized void get(){
        if(!stock) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("用户拿到第"+this.milk+"瓶奶");
        stock = false;
        notifyAll();
    }
}

我们每次 同步方法更改状态后 执行一次notifyAll 唤醒其他的线程

这样我们运行代码如下

在这里插入图片描述
就没有任何问题了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值