生产者消费者模式是一个十分经典的多线程协作的模式,生产者消费者问题主要是包含了两类线程:
-
生产者线程 用于生产数据
-
消费者线程 用于消费数据
为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库。 生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为。 消费者只需要从共享数据区中去获取数据,并不需要关心生产者的行为
下面案例用多线程模拟生产蛋糕:
// 生产者生产蛋糕,将其打包装进箱子(box), 消费者每次消费一个
public class Box {
private int cake; // 箱子中的蛋糕数量
public Box() {
this.cake = 0;
}
// 生产蛋糕
public synchronized void put(int cake) {
// 如果蛋糕超过5个,则等待消费
if (this.cake > 5) {
try {
System.out.println(Thread.currentThread().getName() + "-蛋糕太多了,等待消费...");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
// 生产蛋糕
this.cake += cake;
System.out.println(Thread.currentThread().getName() + "-生产了" + cake + "个蛋糕, 剩余:" + this.cake);
}
// 唤醒其他线程
notifyAll();
}
// 消费蛋糕
public synchronized void get() {
// 如果没有蛋糕,则等待生产
if (this.cake <= 0) {
try {
System.out.println(Thread.currentThread().getName() + "-没有蛋糕了,等待生产...");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
// 消费蛋糕
this.cake--;
System.out.println(Thread.currentThread().getName() + "-消费一个蛋糕, 剩余:" + this.cake);
}
// 唤醒其他线程
notifyAll();
}
}
public class Producer implements Runnable {
private Box box;
public Producer(Box box) {
this.box = box;
}
@Override
public void run() {
for (int i = 1; i < 10; i++) { // 只生产10次
try {
// 生产蛋糕,每次耗费 3~5s
Thread.sleep((long) Math.random() * 5000 + 3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
box.put(i); // 每次生产数量
}
System.out.println(Thread.currentThread().getName() + "-生产结束,该放假了~n");
}
}
public class Customer implements Runnable{
private Box box;
public Customer(Box box) {
this.box = box;
}
@Override
public void run() {
while (true){
try {
// 消费蛋糕
Thread.sleep((long) Math.random() * 3000 + 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
box.get();
}
}
}
public class CakeDemo {
public static void main(String[] args) {
Box box = new Box();
Producer producer = new Producer(box);
Customer customer = new Customer(box);
new Thread(producer, "producer").start();
new Thread(customer, "customer").start();
}
}
运行截图:



