一.概述
1. 什么是“生产者消费者模式”?
生产线程负责生产,消费线程负责消费
生产线程和消费线程要达到均衡。
生产满了就不能继续生产了,必须让消费线程进行消费
消费完了就不能再消费了,必须让生产线程进行生产
这是一种特殊的业务需求,在这种特殊的情况下,需要使用wait()和notify()方法
2.wait和notify方法
wait和notify方法不是线程当中的方法,是任何一个Java 对象 都有的方法(Object自带的,不是线程去调用)
3.wait()方法的作用?
①让正在当前线程(o对象上活动的线程)进入等待状态(Monitor中的waitSet),无期限等待,直到调用o.notify方法被唤醒为止。
②释放所占有的的对象锁
4.notify()方法的作用? (notify: 通知)
对象o.notify可以唤醒正在o对象上等待的线程。只是通知,不会释放对象锁
notifyAll()方法可以唤醒o对象上处于等待的所有线程 / 没有waitAll !
二.简单实现
需求:仓库用List集合表示,List集合中假设只能存储1个元素,1个元素就表示仓库满了
如果List集合中元素的个数是0,就表示仓库空了
保证List集合中永远都是最多存储1个元素
必须做到这种效果:生产1个消费1个。
//生产者
class producer extends Thread{ //创造线程第一种方式private List list;public producer(List list){this.list=list;}@Overridepublic void run() {while(true) { //死循环 反复生产synchronized (list) { // 保证list的线程安全if(list.size()>0){try{list.wait(); //仓库满了则 1.阻塞生产者 2.释放list的对象锁}catch(Exception e){e.printStackTrace();}}else{ //仓库没满,则生产Object o=new Object();list.add(o);System.out.println(Thread.currentThread().getName()+" 生产了:" +o);list.notify(); //生产完了,唤醒list上的消费者进行消费}}}}
}//消费者
class consumer extends Thread{private List list;public consumer(List list){this.list=list;}@Overridepublic void run(){while(true){ //循环 反复消费synchronized (list){if(list.size()==0){try{list.wait(); //如果仓库为空,消费者1.阻塞消费者 2.释放list的对象锁}catch(Exception e){e.printStackTrace();}}else{Object o = list.remove(0); //返回被删除的元素System.out.println(Thread.currentThread().getName()+" 消费了:" +o);list.notify(); //消费了,要唤醒生产者}}}}
}public class test01{public static void main(String[] args) {List list=new ArrayList();Thread t1=new producer(list);Thread t2=new consumer(list);t1.setName("生产者线程");t2.setName("消费者线程");t1.start();t2.start();}
}
效果:
注意:
- 生产完了要唤醒消费者;消费完了要唤醒生产者
- 对象 .wait() 方法会阻塞线程,且会释放对象上的锁;