• java设计模式之生产者/消费者模式


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

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

    生产者消费者模式有如下几个优点:

    1、解耦

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

    2、支持并发

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

    3、支持忙闲不均

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

    生产者-消费者模型准确说应该是“生产者-仓储-消费者”模型,这样的模型遵循如下的规则:

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

     此模型将要结合java.lang.Object的wait与notify、notifyAll方法来实现以上的需求。实例代码如下:

    创建所谓的“仓库”,此类是(本质上:共同访问的)共享数据区域

    //此类是(本质上:共同访问的)共享数据区域
    public class SyncStack {
        
        private String[]  str = new String[10];
        
        private int index;
        
        //供生产者调用
        public synchronized void push(String sst){
            if(index == sst.length()){
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            this.notify();//唤醒在此对象监视器上等待的单个线程 
            str[index] = sst;
            index++;
        }
        
        //供消费者调用  
        public synchronized String pop(){
            if(index == 0){
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            this.notify();
            index--;
            String product = str[index];
            return product;
            
        }
        
        //就是定义一个返回值为数组的方法,返回的是一个String[]引用  
        public String[] pro(){
            return str;
        }
    }

    创建生产者:

    public class Producter implements Runnable {
        
        private SyncStack stack;
        
        public Producter(SyncStack stack){
            this.stack = stack;
        }
        
        public void run(){
            for(int i = 0;i<stack.pro().length;i++){
                String producter = "产品" + i;
                stack.push(producter);
                System.out.println("生产了:" + producter);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            }
        }
    }

    创建消费者:

    public class Consumer implements Runnable {
        
        private SyncStack stack;
        
        public Consumer(SyncStack stack){
            this.stack = stack;
        }
        public void run(){
            for(int i=0;i<stack.pro().length;i++){
                String consumer = stack.pop();
                System.out.println("消费了:" + consumer );
                
                try {
                    Thread.sleep(400);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    测试类:

    public class TestDeam {
    
        public static void main(String[] args) {
            SyncStack stack = new SyncStack();  
            Consumer p = new Consumer(stack);  
            Producter c = new Producter(stack);  
                 
            new Thread(p).start();  
            new Thread(c).start(); 
    
        }
    }

    测试结果:

    生产了:产品0
    消费了:产品0
    生产了:产品1
    生产了:产品2
    消费了:产品2
    生产了:产品3
    消费了:产品3
    生产了:产品4
    生产了:产品5
    生产了:产品6
    消费了:产品5
    生产了:产品7
    消费了:产品6
    消费了:产品7
    生产了:产品8
    生产了:产品9
    消费了:产品8
    消费了:产品9
    消费了:产品4
    消费了:产品1
  • 相关阅读:
    Leetcode:linked_list_cycle
    关于Go语言共享内存操作的小实例
    程序猿如同妓女
    算法——排序算法个人总结
    CentOS 6.4下安装和配置Samba 第2页_服务器应用_Linux公社-Linux系统门户网站
    解决fedora samba在windows下无权限访问的问题
    基于samba实现win7与linux之间共享文件_阳仔_新浪博客
    增加samba用户提示Failed to add entry for user
    Ubuntu+Win7+Samba实现文件共享_Linux教程_Linux公社-Linux系统门户网站
    Mycat 月分片方法
  • 原文地址:https://www.cnblogs.com/conswin/p/6754085.html
Copyright © 2020-2023  润新知