关于生产者 消费者问题

为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
这个阻塞队列就是用来给生产者和消费者解耦的。纵观大多数设计模式,都会找一个第三者出来进行解耦,如工厂模式的第三者是工厂类,模板模式的第三者是模板类。在学习一些设计模式的过程中,如果先找到这个模式的第三者,能帮助我们快速熟悉一个设计模式。

*生产者与消费者模型中,要保证以下几点:
1 同一时间内只能有一个生产者生产 生产方法加锁sychronized
2 同一时间内只能有一个消费者消费 消费方法加锁sychronized
3 生产者生产的同时消费者不能消费 生产方法加锁sychronized
4 消费者消费的同时生产者不能生产 消费方法加锁sychronized
5 共享空间空时消费者不能继续消费 消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行
6 共享空间满时生产者不能继续生产 生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行*“`

模型实例

/*
 * 商品类
 */
public class Good {
int id;
public Good(int id) {
this.id = id;
}
public String toString(){
return "good: "+ id;
}
}

/*
 * 存放生产商品的容器类
 * 生产者将生产的商品存放到这个类
 * 消费者可以从这个类中消费商品
 * 采用的是类似于栈的模型
 */
public class Box {
Good[] good = new Good[6];
int index = 0;
/**  
    * show 生产方法. 
    * show 该方法为同步方法,持有方法锁; 
    * show 首先循环判断满否,满的话使该线程等待,释放同步方法锁,允许消费; 
    * show 当不满时首先唤醒正在等待的消费方法,但是也只能让其进入就绪状态, 
    * show 等生产结束释放同步方法锁后消费才能持有该锁进行消费 
    * @param m 元素 
    * @return 没有返回值  
    */  
public synchronized void push(Good goood){
while(index == good.length){//判断商品是否存满
try {
this.wait();//商品存满进行等待,等待时会让出线程锁,让其他线程先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
good[index] = goood;
index ++;
}

    /**  
    *  消费方法 
    *  该方法为同步方法,持有方法锁 
    *  首先循环判断空否,空的话使该线程等待,释放同步方法锁,允许生产; 
    *  当不空时首先唤醒正在等待的生产方法,但是也只能让其进入就绪状态 
    *  等消费结束释放同步方法锁后生产才能持有该锁进行生产 
    */
public synchronized Good pop(){
while(index ==  0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
index--;
return good[index];
}
}

/*
 * 生产者类
 */
public class Producer implements Runnable{
Box box =new Box();
public Producer(Box box) {
this.box = box;
}
public void run() {
for (int i = 0; i < 20; i++) {
Good good = new Good(i);
box.push(good);
System.out.println("生产了: " +good);
try {//每生产一个商品休眠一段时间
Thread.sleep((int)(Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}  
}
}
}

/*
 * 消费者类
 */
public class Consumer implements Runnable{
Box box = new Box();
public Consumer(Box box) {
this.box = box;
}
public void run() {
for (int i = 0; i < 20; i++) {
Good good = box.pop();
System.out.println("消费的商品是: "+ good);
try {//每消费一个商品休眠一段时间
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}  
}
}
}


/*
 * 测试类
 */
public class Test {
public static void main(String[] args) {
Box box =new Box();
Producer p = new Producer(box);
Consumer c = new Consumer(box);
new Thread(p).start();
new Thread(p).start();
new Thread(c).start();
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值