生产者消费者模式设计模式

原文链接:https://blog.youkuaiyun.com/qq_41247433/article/details/79434202

生产者消费者模式是并发、多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据。

 

真实世界中的生产者消费者模式

生产者和消费者模式在生活当中随处可见,它描述的是协调与协作的关系。比如一个人正在准备食物(生产者),而另一个人正在吃(消费者),他们使用一个共用的桌子用于放置盘子和取走盘子,生产者准备食物,如果桌子上已经满了就等待,消费者(那个吃的)等待如果桌子空了的话。这里桌子就是一个共享的对象。

我们看这样一个例子:

 

生产者:  往一个公共的盒子里面放苹果 

消费者:从公共的盒子里面取苹果

盒子:盒子的容量不能超过5

 

下面我们用两者方法分别实现这样一个场景。

 

方法一:   wait()  和   notify()   通信方法实现

 

看盒子代码

        public class PublicBox { 

           private int apple = 0;     

           public synchronized void increace() { 

               while (apple ==5) { 

                   try { 

                       wait(); 

                   } catch (InterruptedException e) { 

                       e.printStackTrace(); 

                   } 

                  

               } 

               apple++; 

               System. out .println("生成苹果成功!" );

               notify(); 

           }       

           public synchronized void decreace() { 

               while (apple ==0) { 

                   try { 

                       wait(); 

                   } catch (InterruptedException e) { 

                       e.printStackTrace(); 

                   } 

               } 

               apple--; 

              System. out.println( "消费苹果成功!" );

               notify(); 

           } 

          

           public static void main(String []args)

              {

                     PublicBox box= new PublicBox();

                     

                     Consumer con= new Consumer(box);

                     Producer pro= new Producer(box);

                     

                     Thread t1= new Thread(con);

                     Thread t2= new Thread(pro);

                     

                     t1.start();

                     t2.start();

                     

                     

              }

       }

  

生产者代码(定义十次):

 

public class Producer implements Runnable { 

    private PublicBox box; 

 

    public Producer(PublicBox box) { 

        this .box = box; 

    } 

 

    @Override 

    public void run() { 

       

        for( int i=0;i<10;i++)  

       {

               try {

                     System. out .println("pro  i:" +i);

                           Thread. sleep(30);

                     } catch (InterruptedException e) {

                            // TODO: handle exception

                           e.printStackTrace();

                     }

       

            box.increace(); 

       }

        

    } 

}

 

消费者代码(同样十次):

 

public class Consumer implements Runnable { 

    private PublicBox box; 

 

    public Consumer(PublicBox box) { 

        this .box = box; 

    } 

 

    @Override 

    public void run() { 

       

        for( int i=0;i<10;i++)

       {

             try {

                     System. out .println("Con: i " +i);

                           Thread. sleep(3000);                // 这里设置跟上面30不同是为了 盒子中的苹果能够增加,不会生产一个马上被消费  

                     } catch (InterruptedException e) {

                            // TODO: handle exception

                           e.printStackTrace();

                     }

       

            box.decreace(); 

        } 

 } 

}

 

输出如下:

 

pro  i:0

Con: i 0

生成苹果成功!

pro  i:1

生成苹果成功!

pro  i:2

生成苹果成功!

pro  i:3

生成苹果成功!

pro  i:4

生成苹果成功!

pro  i:5

消费苹果成功!

Con: i 1

生成苹果成功!

pro  i:6

消费苹果成功!

Con: i 2

生成苹果成功!

pro  i:7

消费苹果成功!

生成苹果成功!

pro  i:8

Con: i 3

消费苹果成功!

生成苹果成功!

pro  i:9

Con: i 4

消费苹果成功!

生成苹果成功!

Con: i 5

消费苹果成功!

Con: i 6

消费苹果成功!

Con: i 7

消费苹果成功!

Con: i 8

消费苹果成功!

Con: i 9

消费苹果成功!

 


 

方法二:采用阻塞队列实现生产者消费者模式

 

 

 

阻塞队列实现生产者消费者模式超级简单,它提供开箱即用支持阻塞的方法put()和take(),开发者不需要写困惑的wait-nofity代码去实现通信。BlockingQueue 一个接口,Java5提供了不同的现实,如ArrayBlockingQueue和LinkedBlockingQueue,两者都是先进先出(FIFO)顺序。而ArrayLinkedQueue是自然有界的,LinkedBlockingQueue可选的边界。下面这是一个完整的生产者消费者代码例子,对比传统的wait、nofity代码,它更易于理解。

 

盒子代码:

 

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.LinkedBlockingQueue;

 

public class PublicBoxQueue {

 

       

        public static void main(String []args)

       {

               BlockingQueue publicBoxQueue= new LinkedBlockingQueue(5);   //定义了一个大小为5的盒子

              

              Thread pro= new Thread(new ProducerQueue(publicBoxQueue));

              Thread con= new Thread(new ConsumerQueue(publicBoxQueue));

              

              pro.start();

              con.start();

       }

       

}

 

生产者:

 

package dsd;

 

import java.util.concurrent.BlockingQueue;

 

public class ProducerQueue implements Runnable {

 

        private final BlockingQueue proQueue;

       

        public ProducerQueue(BlockingQueue proQueue)

       {

               this .proQueue =proQueue;

       }

 

        @Override

        public void run() {

               // TODO Auto-generated method stub

              

               for (int i=0;i<10;i++)

              {

                      try {

                           System. out .println("生产者生产的苹果编号为 : " +i);  //放入十个苹果编号 为1到10

                            proQueue .put(i);

                           

                            /*Thread.sleep(3000);*/

                     } catch (InterruptedException  e) {

                            // TODO: handle exception

                           e.printStackTrace();

                     }

                     

              }

              

       }

       

       

}

 

消费者:

 

package dsd;

 

import java.util.concurrent.BlockingQueue;

 

public class ConsumerQueue implements Runnable {

 

        private final BlockingQueue conQueue;

       

        public ConsumerQueue(BlockingQueue conQueue)

       {

               this .conQueue =conQueue;

       }

 

        @Override

        public void run() {

               // TODO Auto-generated method stub

               for (int i=0;i<10;i++)

              {

                      try {

                           System. out .println("消费者消费的苹果编号为 :" +conQueue .take());

                           Thread. sleep(3000);  //在这里sleep是为了看的更加清楚些

                           

                     } catch (InterruptedException e) {

                            // TODO: handle exception

                           e.printStackTrace();

                     }

              }

       }

       

       

}

 

结果如下:

 

生产者生产的苹果编号为 : 0

生产者生产的苹果编号为 : 1

消费者消费的苹果编号为 :0

生产者生产的苹果编号为 : 2

生产者生产的苹果编号为 : 3

生产者生产的苹果编号为 : 4

生产者生产的苹果编号为 : 5

生产者生产的苹果编号为 : 6

生产者生产的苹果编号为 : 7

消费者消费的苹果编号为 :1

消费者消费的苹果编号为 :2

生产者生产的苹果编号为 : 8

消费者消费的苹果编号为 :3

生产者生产的苹果编号为 : 9

消费者消费的苹果编号为 :4

消费者消费的苹果编号为 :5

消费者消费的苹果编号为 :6

消费者消费的苹果编号为 :7

消费者消费的苹果编号为 :8

消费者消费的苹果编号为 :9

 

生产者消费者模式的好处

它的确是一种实用的设计模式,常用于编写多线程或并发代码。下面是它的一些优点:

  1.  它简化的开发,你可以独立地或并发的编写消费者和生产者,它仅仅只需知道共享对象是谁
  2. 生产者不需要知道谁是消费者或者有多少消费者,对消费者来说也是一样
  3.  生产者和消费者可以以不同的速度执行
  4.  分离的消费者和生产者在功能上能写出更简洁、可读、易维护的代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值