Java设计模式之生产者/消费者模式

Posted 红日666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java设计模式之生产者/消费者模式相关的知识,希望对你有一定的参考价值。

一、什么是生产者/消费者模式?

某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。在生产者与消费者之间在加个缓冲区,我们形象的称之为仓库,生产者负责往仓库了进商品,而消费者负责从仓库里拿商品,这就构成了生产者消费者模式。

结构图如下:


二、生产者消费者模式的优点:

1、解耦:

由于有缓冲区的存在,生产者和消费者之间不直接依赖,耦合度降低。

2、支持并发:

由于生产者与消费者是两个独立的并发体,他们之间是用缓冲区作为桥梁连接,生产者只需要往缓冲区里丢数据,就可以继续生产下一个数据,而消费者只需要从缓冲区了拿数据即可,这样就不会因为彼此的处理速度而发生阻塞。

3、支持忙闲不均:

缓冲区还有另一个好处。如果制造数据的速度时快时慢,缓冲区的好处就体现出来 了。当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。 等生产者的制造速度慢下来,消费者再慢慢处理掉。


三、生产者-消费者模型【即“生产者-仓储-消费者”】模型遵循的规则:

1、生产者仅仅在仓储未满时候生产,仓满则停止生产。
2、消费者仅仅在仓储有产品时候才能消费,仓空则等待。
3、当消费者发现仓储没产品可消费时候会通知生产者生产。
4、生产者在生产出可消费产品时候,应该通知等待的消费者去消费。

四、源码示例:

1、仓库:
/**
 * 仓库【即共享数据区域】
 */
public class SyncStack 

    private String[] strArray = new String[10];

    private int index;

    /**
     * 供生产者调用
     *
     * @param str
     */
    public synchronized void push(String str) 
        if (index == strArray.length) 
            try 
                wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        //唤醒在此对象监视器上等待的单个线程
        notify();
        strArray[index] = str;
        index++;
    

    /**
     * 供消费者调用
     *
     * @return
     */
    public synchronized String pop() 
        if (index == 0) 
            try 
                wait();
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        notify();
        index--;
        return strArray[index];
    

    /**
     * 定义一个返回值为数组的方法,返回的是一个String[]引用
     */
    public String[] getStrArray() 
        return strArray;
    


2、生产者:
/**
 * 生产者
 */
public class Producer implements Runnable

    private SyncStack stack;

    public Producer(SyncStack stack)
        this.stack = stack;
    

    @Override
    public void run() 
        for (int i = 0; i < stack.getStrArray().length; i++) 
            String producer = "产品" + i;
            stack.push(producer);
            System.out.println("生产了 ---> " + producer);

            try 
                Thread.sleep(300);
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
    


3、消费者:
/**
 * 消费者
 */
public class Consumer implements Runnable

    private SyncStack stack;

    public Consumer(SyncStack stack) 
        this.stack = stack;
    

    @Override
    public void run() 
        for (int i = 0; i < stack.getStrArray().length; i++) 
            String consumer = stack.pop();
            System.out.println("消费了 ---> " + consumer);

            try 
                Thread.sleep(500);
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
    




测试结果:





参考:
Java设计模式综述

以上是关于Java设计模式之生产者/消费者模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式之生产者/消费者模式

Java设计模式之生产者/消费者模式

Java设计模式之生产者/消费者模式

Java设计模式之生产者/消费者模式

java 多线程并发系列之 生产者消费者模式的两种实现

Java多线程之并发协作生产者消费者设计模式