-为什么会提出生产者-消费者模式?
-是为了更好处理并发程序设计中进程同步问题。解决生产速率和消费速率不匹配的问题,如果不使用生产者消费者模式,生产速度过快,而消费者处理速度过慢,则必须等待消费者处理完才能继续生产;同样如果消费者处理速度大于生产者处理速度,那么消费者必须等待生产者生产了才能继续处理。而生产者-消费者模式通过引入一个生产者与消费者公用的缓冲区可以解决这个问题,大大提高了处理速率。
-什么是生产者-消费者问题?
-所谓生产者-消费者问题,可以抽象成:一组生产者向一组消费者提供产品,生产者与消费者共享一个有界缓冲池,生产者向其中投放产品,消费者从中取出产品消费。其中所谓消费者是指使用某一软硬件资源的进程,而生产者是指提供(释放)某一软硬件资源的进程。
下面是一段没有使用生产者-消费者模式的代码:
public class Product {
private int count=0; // 商品数量
private final int MAX=5; // 库存最大值
// 生产商品
public synchronized void makeProduct(){
String threadName=Thread.currentThread().getName();
if(count>=MAX){
System.out.println("货物已满,"+threadName+"停止生产");
try {
notifyAll(); // 每生产一个商品,则通知(唤醒)所有等待着的消费者线程
wait(); // 生产者线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++; // 模拟生产
System.out.println(threadName+"生产了产品,目前商品总量:"+count);
notifyAll(); // 每生产一个商品,则通知(唤醒)所有等待着的消费者线程
}
}
// 消费商品
public synchronized void buyProduct(){
String threadName=Thread.currentThread().getName();
if(count<=0){
System.out.println(threadName+",已无货,请等待......");
notifyAll(); // 通知所有生产者线程
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--; // 模拟买商品
System.out.println(threadName+"买了一个商品,当前还剩余商品数量:"+count);
}
}
}
public class Consumer implements Runnable{
private Product product;
public Consumer(Product product){
this.product=product;
}
@Override
public void run() {
while(true){
product.buyProduct();
}
}
}
public class Producer implements Runnable{
private Product product;
public Producer(Product product){
this.product=product;
}
@Override
public void run() {
while(true){
product.makeProduct();
}
}
}
public class Test {
public static void main(String[] args) {
Product pro=new Product();
new Thread(new Producer(pro),"1号生产者").start(); // 启动1号生产者线程
new Thread(new Producer(pro),"2号生产者").start(); // 启动2号生产者线程
new Thread(new Consumer(pro),"A号消费者").start(); // 启动A号消费者线程
new Thread(new Consumer(pro),"B号消费者").start(); // 启动B号消费者线程
// new Thread(new Consumer(pro),"C号消费者").start(); // 启动C号消费者线程
}
}