• Java设计模式—生产者消费者模式(阻塞队列实现)


    生产者消费者模式是并发、多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据。这篇文章我们来看看什么是生产者消费者模式,这个问题也是多线程面试题中经常被提及的。如何使用阻塞队列(Blocking Queue)解决生产者消费者模式,以及使用生产者消费者模式的好处。

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

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

    生产者消费者模式的好处

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

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

    多线程中的生产者消费者问题

    生产者消费者问题是一个流行的面试题,面试官会要求你实现生产者消费者设计模式,以至于能让生产者应等待如果队列或篮子满了的话,消费者等待如果队列或者篮子是空的。这个问题可以用不同的方式来现实,经典的方法是使用wait和notify方法在生产者和消费者线程中合作,在队列满了或者队列是空的条件下阻塞,Java5的阻塞队列(BlockingQueue)数据结构更简单,因为它隐含的提供了这些控制,现在你不需要使用wait和nofity在生产者和消费者之间通信了,阻塞队列的put()方法将阻塞如果队列满了,队列take()方法将阻塞如果队列是空的。在下部分我们可以看到代码例子。

    使用阻塞队列实现生产者消费者模式

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

    点击(此处)折叠或打开

    1. import java.util.concurrent.BlockingQueue;
    2. import java.util.concurrent.LinkedBlockingQueue;
    3. import java.util.logging.Level;
    4. import java.util.logging.Logger;
    5.  
    6. public class ProducerConsumerPattern {
    7.  
    8.     public static void main(String args[]){
    9.  
    10.      //Creating shared object
    11.      BlockingQueue sharedQueue = new LinkedBlockingQueue();
    12.  
    13.      //Creating Producer and Consumer Thread
    14.      Thread prodThread = new Thread(new Producer(sharedQueue));
    15.      Thread consThread = new Thread(new Consumer(sharedQueue));
    16.  
    17.      //Starting producer and Consumer thread
    18.      prodThread.start();
    19.      consThread.start();
    20.     }
    21.  
    22. }
    23.  
    24. //Producer Class in java
    25. class Producer implements Runnable {
    26.  
    27.     private final BlockingQueue sharedQueue;
    28.  
    29.     public Producer(BlockingQueue sharedQueue) {
    30.         this.sharedQueue = sharedQueue;
    31.     }
    32.  
    33.     @Override
    34.     public void run() {
    35.         for(int i=0; i<10; i++){
    36.             try {
    37.                 System.out.println("Produced: " + i);
    38.                 sharedQueue.put(i);
    39.             } catch (InterruptedException ex) {
    40.                 Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
    41.             }
    42.         }
    43.     }
    44.  
    45. }
    46.  
    47. //Consumer Class in Java
    48. class Consumer implements Runnable{
    49.  
    50.     private final BlockingQueue sharedQueue;
    51.  
    52.     public Consumer (BlockingQueue sharedQueue) {
    53.         this.sharedQueue = sharedQueue;
    54.     }
    55.  
    56.     @Override
    57.     public void run() {
    58.         while(true){
    59.             try {
    60.                 System.out.println("Consumed: "+ sharedQueue.take());
    61.             } catch (InterruptedException ex) {
    62.                 Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
    63.             }
    64.         }
    65.     }
    66.  
    67. }
    68.  
    69. Output:
    70. Produced: 0
    71. Produced: 1
    72. Consumed: 0
    73. Produced: 2
    74. Consumed: 1
    75. Produced: 3
    76. Consumed: 2
    77. Produced: 4
    78. Consumed: 3
    79. Produced: 5
    80. Consumed: 4
    81. Produced: 6
    82. Consumed: 5
    83. Produced: 7
    84. Consumed: 6
    85. Produced: 8
    86. Consumed: 7
    87. Produced: 9
    88. Consumed: 8
    89. Consumed: 9

        来源:http://www.importnew.com/6695.html

  • 相关阅读:
    div+css之清除浮动
    ASP.NET repeater添加序号列的方法
    html中给图片添加热点
    jquery中read与js中onload区别
    从.net转型,聊聊最近一些面试,薪资和想法
    (9)分布式下的爬虫Scrapy应该如何做-关于ajax抓取的处理(一)
    数学之美--关于图论引申出来的爬虫构想
    (8)分布式下的爬虫Scrapy应该如何做-图片下载(源码放送)
    【转】Bloom Filter布隆过滤器的概念和原理
    【转】Python中的GIL、多进程和多线程
  • 原文地址:https://www.cnblogs.com/yxgyiwen/p/6600945.html
Copyright © 2020-2023  润新知