目录
一.简要介绍
生产者消费者模型是多线程的经典例子
1.涉及的两类线程:
- 用生产者线程执行生产数据
- 用消费者线程执行消费数据
- 而两者交集的共享数据区域就像是一个仓库,仓库的容量是有限的
- 生产者生产数据后放入仓库中,不需要care消费者有什么样的行为
- 消费者从仓库之中拿数据,不需要care生产者有什么样的行为
生产者——仓库——消费者 ,如果不能做到时间连续,生产者不能及时生产数据,消费者不能及时取出数据,就会产生等待和唤醒问题,而Java程序正好可以用来解决这个问题。
2.涉及的java程序
java中object类中的三个方法
- wait() 等待功能,使当前程序等待,直到另一个线程调用这个对象的notify()和notifyAll()
- notify() 唤醒功能,唤醒正在等待对象监视器的单个线程
- notifyAll() 唤醒功能,唤醒正在等待对象监视器的所有线程
二.少说多做,直接上代码
需要建立四个部分,分别是生产者、消费者、仓库、主程序。
快递小哥=生产者,产品=包裹 ,仓库=快递柜
1.建立生产者
public class Producer implements Runnable {
private Warehouse w;
public Producer(Warehouse w){
this.w =w;
}
@Override
public void run(){
for(int i=1;i<=60;i++){
w.put(i);
}
}
}
2.建立消费者
public class Consumer implements Runnable {
private Warehouse w;
public Consumer(Warehouse w){
this.w = w;
}
@Override
public void run() {
while(true){
w.get();
}
}
}
3.建立仓库
public class Warehouse {
//定义一个成员变量,表示第几个快递
private int parcel;
//定义一个成员变量,表示仓库的状态
private boolean state = false;
//提供存储快递和获取快递的操作
//生产投递
public synchronized void put(int parcel ) {
//如果有包裹就等待消费
if(state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有包裹,就生产投递包裹
this.parcel = parcel;
System.out.println("快递小哥将第"+this.parcel+"个快递包裹放入货柜");
//投递完毕之后,修改仓库状态
state = true;
//唤醒其他等待的线程
notifyAll();
}
//得到
public synchronized void get(){
//如果没有包裹,就等待生产投递
if (!state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有包裹,就取出包裹
System.out.println("消费者拿到第"+this.parcel+"个快递包裹");
//取到包裹之后,就修改仓库状态
state = false;
//唤醒其他等待的线程
notifyAll();
}
}
4.建立主程序
public class main {
public static void main(String[] args){
//创建仓库对象,这是共享数据区域
Warehouse w = new Warehouse();
//创建生产者对象,把仓库对象作为构造方法参数传递,因为在这个类中要调用存储包裹的操作
Producer p = new Producer(w);
//创建消费者对象,把仓库对象作为构造方法参数传递,因为在这个类中要调用获取包裹的操作
Consumer c = new Consumer(w);
//创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
//启动线程
t1.start();
t2.start();
}
}