一、问题描述
生产者消费者问题(Producer-consumer problem),也称有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例。生产者生成一定量的数据放到缓冲区中,然后重复此过程;与此同时,消费者也在缓冲区消耗这些数据。生产者和消费者之间必须保持同步,要保证生产者不会在缓冲区满时放入数据,消费者也不会在缓冲区空时消耗数据。不够完善的解决方法容易出现死锁的情况,此时进程都在等待唤醒。
二、简化问题
所谓生产者消费者问题,实际上主要是两类线程:
一类是生产者线程用于生产数据
一类是消费者线程用于消费数据
还有一个类时用来保存数据的,通常会采用共享的数据区域,就像一个仓库一样
生产者生产数据之后直接放置在共享数据库中,不需要关心消费者的行为
消费者只需要从共享数据库中去获取数据,不需要关心生产者的行为
三、案例:
生产者消费者案例中包含的类:
奶箱类:提供存储牛奶和获取牛奶的操作
生产者类:实现Runnable接口,重写run()方法,调用存储牛奶的操作
消费者类:实现Runnable接口,重写run()方法,调用获取牛奶的操作
测试类
代码实现:
//这个类就相当于共享的数据区
//在这个类中是代表装奶盒,里面最多能装10瓶奶
public class Box {
private final int mile_max=10;
//这就是一个容器,用来存放奶的
LinkedList<Object> list=new LinkedList<>();
//放奶
public synchronized void put(){
//此时说明牛奶箱已经满了,不需要在进行产奶了
while(list.size()+1>mile_max){
System.out.println("【生产者:"+Thread.currentThread().getName()+"】仓库已满");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果牛奶箱不满的话,就可以往牛奶箱中进行添加牛奶
list.add(new Object());
System.out.println("【生产者:"+Thread.currentThread().getName()+"】生产一个产品,现库存"+list.size());
notifyAll();
}
//取奶
public synchronized void get(){
//如果牛奶箱中没有牛奶,让消费者进行等待,等待牛奶的生产
while(list.size()==0){
System.out.println("【消费者:"+Thread.currentThread().getName()+"】仓库已空");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果牛奶箱中有牛奶,消费者可以进行拿牛奶操作
list.remove();
System.out.println("【消费者:"+Thread.currentThread().getName()+"】消费一个产品,现库存"+list.size());
notifyAll();
}
}
//这个类就是生产者类
//把牛奶往牛奶箱中进行放牛奶
public class Producer implements Runnable {
private Box b;
//这是生产者的无参和有参构造方法
public Producer(){}
public Producer(Box b){
this.b=b;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
b.put();
}
}
}
//这个类就是消费者类
//消费者进行消费牛奶
public class Customer implements Runnable {
private Box b;
public Customer(){}
//模拟消费者从箱子中进行消费牛奶
public Customer(Box b){
this.b=b;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
b.get();
}
}
}
//下面是我的测试类
public class TestDemo {
public static void main(String[] args) {
//三个生产者三个消费者
Box b=new Box();
Producer p1=new Producer(b);
Customer c1=new Customer(b);
Producer p2=new Producer(b);
Customer c2=new Customer(b);
Producer p3=new Producer(b);
Customer c3=new Customer(b);
Thread t1=new Thread(p1);
Thread t2=new Thread(p2);
Thread t3=new Thread(p3);
Thread t4=new Thread(c1);
Thread t5=new Thread(c2);
Thread t6=new Thread(c3);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}