@生产消费模型@

1.何为生产消费模型

项目中,需要生产对象放入仓库中,也需要从仓库中取出对象消费对象,对象的生产消费过程构成了生产消费模型。

2.生产过程

1.判断仓库容量,检测是否可以存放数据

2.如果仓库已满,让生产者进入等待状态

3.如果仓库没满,向仓库中添加数据,并通知消费者仓库中有数据

示例:

package com.zq1008;


/*生产消费模型
生产者线程
锁必须唯一,为线程对象所共有,锁对象和等待对象一致,当前线程的等待对象和唤醒对象一致,唤醒对象和锁对象一致,避免锁住了,不是一个对象唤醒不了
if else 当线程停止后,不会执行if后面的语句
int为基本数据类型不是对象,int的包装类Integer是对象
当阻塞方法收到中断请求的时候就会抛出InterruptedException异常
唤醒消费者线程,消费者锁对象还没上锁,启动失败
 */

public class Production implements Runnable{
    Ticket ticket;



    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //锁住了ticket,一次只能一个线程操作对象
            //锁必须唯一,为线程对象所共有
            synchronized (ticket){
                //1.判断仓库容量,检测是否可以存放数据
                //2.如果仓库已满,让生产者进入等待状态
                if (ticket.ticketnum >= 100) {

                    //生产者进入等待状态
                    //锁和调用wait()方法的对象一致
                    //生产过程加锁,防止出现线程安全
                    try {
                        System.out.println("生产者挂起");
                        ticket.wait();   //释放了锁   等待对象唯一,锁对象共有不唯一,唤醒对象不一致
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //3.如果仓库没满,向仓库中添加数据,唤醒消费者,边生产边消费
                else {
                    ticket.ticketnum++;
                    //唤醒消费者
                    //if中为生产者线程暂停,else不会执行,且else中无睡眠的生产者,所以唤醒的只是消费者,如果消费者全被唤醒,不用唤醒了,
                    ticket.notify();
                }
                System.out.println("生产者线程"+Thread.currentThread().getName()+"生产商品" + ticket.ticketnum);

            }
        }
    }
}



注意:

1.生产过程加锁,防止出现线程安全

2.锁和调用wait()方法的代码块一致

3.消费过程

  1. 判断仓库中是否有数据
  2. 若仓库中无数据,让消费者线程进入等待状态,并通知生产者生产数据
  3. 若仓库中有数据,进行消费过程

示例:

package com.zq1008;


//消费者线程
public class Consumption extends Thread {

    Ticket ticket;


    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //消费过程
            //1.判断仓库中是否有数据
            //2.仓库中无数据,让消费者线程进入等待状态

            //锁必须唯一,线程对象所共有
            synchronized (ticket) {
                if (ticket.ticketnum == 0) {
                    //消费者进入等待状态
                    try {
                        System.out.println("消费者挂起");
                        ticket.wait();

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //3.仓库中有数据,进行消费过程,唤醒生产者,边消费边生产
                else {
                    System.out.println("消费者线程启动了");
                    ticket.ticketnum--;
                    //唤醒生产者
                    //if中为消费者暂停,else中不会执行,且else中无睡眠的消费者,所以唤醒的是消费者,
                        System.out.println("唤醒生产者");
                        ticket.notify();
                    }
                }
            System.out.println("消费者线程"+Thread.currentThread().getName()+"消费商品" + ticket.ticketnum);
            }

        }
    }

注意

1.和生产过程一样,消费过程加锁,防止出现线程安全

2.锁和调用wait()方法的代码块一致

4.wait和sleep的区别

1.wait()方法属于Object类,sleep()属于Thread类

3.sleep()必须指定时间,wait()可以指定时间也可以不指定,sleep()时间到,线程处于临时阻塞或运行状态

2.wait()方法释放cpu给其他线程,自己让出资源进入等待池等待;sleep占用cpu,不让出资源

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值