生产者消费者案例
- 主要包含两类线程
- 一类是生产者线程用于生产数据
- 一类是消费者线程用于消费数据
-
为了解耦生产者和消费者的关系,通常会采用共享的数据区域,生产者生产放进共享区域,消费者从共享区域消费
-
生产和消费过程中的等待和唤醒方法(
用synchronized修饰方法保证线程安全)
- void wait()导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法
- void notify()唤醒正在等待对象监视器的单个线程
- void notifyAll ()唤醒正在等待对象监视器的所有线程
- 生产者类
/*
生产者线程类
*/
public class Producer implements Runnable {
private Box box;
public Producer(Box b) {
this.box=b;
}
@Override
public void run() {
// 调用生产牛奶的方法
for (int i = 1; i < 15; i++) {
box.putMilk(i);
}
}
}
- 消费者类
/*
消费者线程类,
*/
public class Consumer implements Runnable {
private Box box;
// 给变量box赋值为创建的Box对象
public Consumer(Box b) {
this.box=b;
}
@Override
public void run() {
// 调用消费牛奶的方法
while(true){
box.takeMilk();
}
}
}
- 共享区域类和操作类
/*
盒子作为共享数据区域
*/
public class Box {
// 定义一个成员变量,表示第x瓶奶
private int milk;
// 定义一个成员变量,表示奶箱的状态,初始值为false
private Boolean state = false;
// 存储牛奶
public synchronized void putMilk(int milk) {
if (state) {
// 奶箱中有牛奶,调用wait()方法等待消费者消费
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 奶箱中没有牛奶,生产牛奶
this.milk = milk;
System.out.println("用户将第" + this.milk + "放入奶箱");
// 生产完之后,修改奶箱状态,并唤醒进程
state = true;
notifyAll();
}
// 消费牛奶的方法,使用同步方法保证线程安全
public synchronized void takeMilk() {
if (!state) {
// 奶箱中没有牛奶,等待生产
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 奶箱中有牛奶,用户消费牛奶
System.out.println("用户将第" + this.milk + "取出奶箱");
// 消费完,修改奶箱状态,并唤醒进程
state = false;
notifyAll();
}
}
/*
线程类
*/
public class TestDemo {
public static void main(String[] args) {
// 创建奶箱对象,用于对象传递
Box b=new Box();
// 创建生产者和消费者线程对象
Producer p=new Producer(b);
Consumer c=new Consumer(b);
Thread producer=new Thread(p);
Thread consumer=new Thread(c);
// 启动线程
producer.start();
consumer.start();
}
}