生产者消费者模型:
生产者在将产品加入仓库中之后通知所有正在挂起的消费者消费产品
消费者在消费产品,导致仓库为空之后,通知所有正在挂起的生产者继续生产
线程间通信依赖的方法:
wait():执行wait()方法的线程将进入挂起状态,挂起状态的线程会释放资源对象(仓库对象),不会自动唤醒
notify():执行notify()方法的线程,将会从线程池当中随机唤醒一个处于挂起状态的线程,但是唤醒哪一个线程是随机的
notifyAll():执行notifyAll()方法的线程,将会向线程池中所有的线程都发送一个唤醒信号,
正在处于活跃状态的线程将会忽略这个信号,所有处于挂起状态的线程都将响应这个信号,重新进入活跃状态
注意:这3个方法并不是定义在Thread类型中的,而是定义在Object类型中的,所以任何对象都能够调用这3个方法
线程间通信的流程:(Thread t1 Thread t2 Object obj)
1.线程t1使用obj对象作为锁对象进入锁环境(sychronized代码段中)
2.线程t1调用obj对象的wait()方法,使当前线程进入挂起状态
3.线程t2使用obj对象作为锁对象进入锁环境
4.线程t2调用obj对象的notify()/notifyAll()方法唤醒线程t1
注意:在线程间通信过程当中:等待加锁对象 + 执行等待方法的对象 + 唤醒加锁对象 + 执行唤醒方法的对象
上述的4个对象必须保证是同一个对象
因为当一个线程在执行挂起的时候,这个线程就绑定在了执行wait()方法的对象上
如果不使用同一个对象执行唤醒功能,唤醒的将不是之前执行挂起的线程
从这个角度来讲,我们一般选择多个线程之间的共享资源对象作为锁对象和执行挂起方法和唤醒方法的对象
设计生产者/消费者线程应该执行的操作流程:
生产者线程:Producer
1.传递一个共享的仓库对象
2.生产功能:
2.1判断仓库中是否有空闲空间,如果没有空闲空间,当前生产者线程进入挂起状态
2.2没有挂起说明当前仓库中有空闲空间,执行生产,将产品加入仓库中
2.3通知(唤醒)其他消费者线程,进入活跃状态,执行消费方法
3.重写run方法,重复执行生产方法
消费者线程:Consumer
1.传递一个共享的仓库对象
2.消费方法:
2.1判断消费的仓库中是否存在产品,如果仓库为空,当前消费者线程将进入挂起状态
2.2如果消费者线程从挂起状态唤醒,说明有产品加入仓库,消费者执行消费方法,将仓库清空
2.3通知(唤醒)其他生产者线程,进入活跃状态,执行生产方法
3.重写run方法,重复执行消费方法
生产者代码
在这里插入代码片/**
* 生产者线程
* @author 80769
*
*/
public class Produce extends Thread{
private Room room;
public Produce(String name,Room room) {
super(name);
this.room=room;
}
public void produce() throws InterruptedException {
synchronized (room) {
while(room.thing!=null) {
room.wait();
}
String thing =Long.toString(System.currentTimeMillis());
System.out.println(this.getName()+"生产产品"+thing);
room.thing=thing;
room.notifyAll(); //如果是一个生产者使用(notify)
}
Thread.sleep(100);
}
public void run() {
while(true) {
try {
produce();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
消费者
/**
* 生产者线程
* @author 80769
*
*/
public class Produce extends Thread{
private Room room;
public Produce(String name,Room room) {
super(name);
this.room=room;
}
public void produce() throws InterruptedException {
synchronized (room) {
while(room.thing!=null) {
room.wait();
}
String thing =Long.toString(System.currentTimeMillis());
System.out.println(this.getName()+"生产产品"+thing);
room.thing=thing;
room.notifyAll();
}
Thread.sleep(100);
}
public void run() {
while(true) {
try {
produce();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
运行结果
这只是一种生产和消费者的实现方法
还有别的方式实现生产者和消费者模式,可以参考:https://juejin.im/entry/596343686fb9a06bbd6f888c