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.消费过程
- 判断仓库中是否有数据
- 若仓库中无数据,让消费者线程进入等待状态,并通知生产者生产数据
- 若仓库中有数据,进行消费过程
示例:
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,不让出资源