TA的每日心情  | 开心 2021-12-13 21:45 | 
|---|
 
  签到天数: 15 天 [LV.4]偶尔看看III  
 | 
 
| 
 
   
  
   
 
  
  
   
    
   
   
   生产者消费者模式是并发、多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据。这篇文章我们来看看什么是生产者消费者模式,这个问题也是多线程面试题中经常被提及的。如何使用阻塞队列(Blocking Queue)解决生产者消费者模式,以及使用生产者消费者模式的好处。 
   真实世界中的生产者消费者模式 
   生产者和消费者模式在生活当中随处可见,它描述的是协调与协作的关系。比如一个人正在准备食物(生产者),而另一个人正在吃(消费者),他们使用一个共用的桌子用于放置盘子和取走盘子,生产者准备食物,如果桌子上已经满了就等待,消费者(那个吃的)等待如果桌子空了的话。这里桌子就是一个共享的对象。在java Executor框架自身实现了生产者消费者模式它们分别负责添加和执行任务。 
   生产者消费者模式的好处 
   它的确是一种实用的设计模式,常用于编写多线程或并发代码。下面是它的一些优点: 
    
     它简化的开发,你可以独立地或并发的编写消费者和生产者,它仅仅只需知道共享对象是谁 
    生产者不需要知道谁是消费者或者有多少消费者,对消费者来说也是一样 
     生产者和消费者可以以不同的速度执行 
     分离的消费者和生产者在功能上能写出更简洁、可读、易维护的代码 
    
   多线程中的生产者消费者问题 
   生产者消费者问题是一个流行的面试题,面试官会要求你实现生产者消费者设计模式,以至于能让生产者应等待如果队列或篮子满了的话,消费者等待如果队列或者篮子是空的。这个问题可以用不同的方式来现实,经典的方法是使用wait和notify方法在生产者和消费者线程中合作,在队列满了或者队列是空的条件下阻塞,Java5的阻塞队列(BlockingQueue)数据结构更简单,因为它隐含的提供了这些控制,现在你不需要使用wait和nofity在生产者和消费者之间通信了,阻塞队列的put()方法将阻塞如果队列满了,队列take()方法将阻塞如果队列是空的。在下部分我们可以看到代码例子。 
   使用阻塞队列实现生产者消费者模式 
   阻塞队列实现生产者消费者模式超级简单,它提供开箱即用支持阻塞的方法put()和take(),开发者不需要写困惑的wait-nofity代码去实现通信。BlockingQueue 一个接口,Java5提供了不同的现实,如ArrayBlockingQueue和LinkedBlockingQueue,两者都是先进先出(FIFO)顺序。而ArrayLinkedQueue是自然有界的,LinkedBlockingQueue可选的边界。下面这是一个完整的生产者消费者代码例子,对比传统的wait、nofity代码,它更易于理解。 
 
 
    
     
     点击(此处)折叠或打开 
     
     
      
      import java.util.concurrent.BlockingQueue; 
 
      import java.util.concurrent.LinkedBlockingQueue; 
 
      import java.util.logging.Level; 
 
      import java.util.logging.Logger; 
 
        
 
      public class ProducerConsumerPattern { 
 
        
 
          public static void main(String args[]){ 
 
        
 
           //Creating shared object 
 
           BlockingQueue sharedQueue = new LinkedBlockingQueue(); 
 
        
 
           //Creating Producer and Consumer Thread 
 
           Thread prodThread = new Thread(new Producer(sharedQueue)); 
 
           Thread consThread = new Thread(new Consumer(sharedQueue)); 
 
        
 
           //Starting producer and Consumer thread 
 
           prodThread.start(); 
 
           consThread.start(); 
 
          } 
 
        
 
      } 
 
        
 
      //Producer Class in java 
 
      class Producer implements Runnable { 
 
        
 
          private final BlockingQueue sharedQueue; 
 
        
 
          public Producer(BlockingQueue sharedQueue) { 
 
              this.sharedQueue = sharedQueue; 
 
          } 
 
        
 
          @Override 
 
          public void run() { 
 
              for(int i=0; i<10; i++){ 
 
                  try { 
 
                      System.out.println("Produced: " + i); 
 
                      sharedQueue.put(i); 
 
                  } catch (InterruptedException ex) { 
 
                      Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex); 
 
                  } 
 
              } 
 
          } 
 
        
 
      } 
 
        
 
      //Consumer Class in Java 
 
      class Consumer implements Runnable{ 
 
        
 
          private final BlockingQueue sharedQueue; 
 
        
 
          public Consumer (BlockingQueue sharedQueue) { 
 
              this.sharedQueue = sharedQueue; 
 
          } 
 
        
 
          @Override 
 
          public void run() { 
 
              while(true){ 
 
                  try { 
 
                      System.out.println("Consumed: "+ sharedQueue.take()); 
 
                  } catch (InterruptedException ex) { 
 
                      Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex); 
 
                  } 
 
              } 
 
          } 
 
        
 
      } 
 
        
 
      Output: 
 
      Produced: 0 
 
      Produced: 1 
 
      Consumed: 0 
 
      Produced: 2 
 
      Consumed: 1 
 
      Produced: 3 
 
      Consumed: 2 
 
      Produced: 4 
 
      Consumed: 3 
 
      Produced: 5 
 
      Consumed: 4 
 
      Produced: 6 
 
      Consumed: 5 
 
      Produced: 7 
 
      Consumed: 6 
 
      Produced: 8 
 
      Consumed: 7 
 
      Produced: 9 
 
      Consumed: 8 
 
      Consumed: 9 
      
     
    
   
   
 |   
 
 
 
 |