`

生产者-消费者-BlockingQueue

阅读更多

本人技术博客: http://demi-panda.com 

 

 

  本例介绍一个特殊的队列:BlockingQueue,如果BlockingQueue是空的,从BlockingQueue取东西的操作将会被阻断进入 等待状态,直到BlockingQueue进了东西才会被唤醒,同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等 待状态,直到BlockingQueue里有空间时才会被唤醒继续操作。
       本例再次实现前面介绍的篮子程序,不过这个篮子中最多能放得苹果数不是1,可以随意指定。当篮子满时,生产者进入等待状态,当篮子空时,消费者等待。

       BlockingQueue定义的常用方法如下:
                add(anObject):把anObject加到BlockingQueue里,如果BlockingQueue可以容纳,则返回true,否则抛出异常。
                offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false。
                put(anObject):把anObject加到BlockingQueue里,如果BlockingQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里有空间再继续。
                poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null。
                take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的对象被加入为止。

       BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类:
                ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小。其所含的对象是以FIFO(先入先出)顺序排序的。
                LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue 有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定。其所含的对象是以FIFO顺序排序 的。
                PriorityBlockingQueue:类似于LinkedBlockingQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数所带的Comparator决定的顺序。
                SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的。

       LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致 LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于 ArrayBlockingQueue。

 

package com.yoyosys.smartstorage.consumer;

import java.util.concurrent.BlockingQueue;
/**
 * to-do.
 *
 * @author Denghaiping
 * @version 1.0
 */
public class Fetcher implements Runnable
{
  @SuppressWarnings("unused")
  private BlockingQueue<String> queue = null ;

  public Fetcher(BlockingQueue<String> queue)
  {
    this.queue = queue;
  }

  public void run() 
  {
    try {
      while (true) {
        queue.put("segment-name-"+i);
        System.out.println("ThreadName : "+ Thread.currentThread().getName() +" 抓取完成");
      }   
    } catch (InterruptedException ex) {
      ex.printStackTrace();    
    }   
  }
}                                                                                                                                                                      


 

 */
package com.yoyosys.smartstorage.consumer;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
 * to-do.
 *
 * @author Denghaiping
 * @version 1.0
 */
public class Indexer implements Runnable
{

  private  BlockingQueue<String> queue ;
  public Indexer(BlockingQueue<String> queue)
  {
    this.queue = queue;
  }

  public void run()
  {
    try {
      while(true) {
        Thread.sleep(1000);
        String name = queue.take();
        System.out.println("ThreadName : " +Thread.currentThread().getName()+ " 索引创建完成 " +name);
      }
    } catch (InterruptedException ex) {
      ex.printStackTrace(); 
    }
  }
} 


 

package com.yoyosys.smartstorage.consumer;

import java.util.concurrent.*;

/**
 * to-do.
 *
 * @author Denghaiping
 * @version 1.0
 */
public class TestConsumer
{
  private static BlockingQueue<String> queue = new ArrayBlockingQueue<String> (10);
  
  
  public static void main(String [] args) 
  {
    ExecutorService service = Executors.newCachedThreadPool();  
    Fetcher producer = new Fetcher(queue);  
    Indexer consumer = new Indexer(queue);  
    Indexer consumer1 = new Indexer(queue);  
    service.submit(producer);  
    service.submit(consumer);
    service.submit(consumer1);
    // 程序运行5s后,所有任务停止  
    try {
      Thread.sleep(5000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    //service.shutdownNow();  
  }
}


 

 

分享到:
评论
2 楼 josico 2014-04-24  
有几个问题想问下楼主
1. LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致 LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于 ArrayBlockingQueue。
能不能解释下,为什么列表和数组,两种数据类型会产生这样的差异

2.能不能解释下另外2个queue啥作用。。。。

1 楼 annybz 2013-09-26  
有没有关于 BlockingQueue和ConcurrentLinkQueue 性能比较的文章?

相关推荐

    模拟“生产者-消费者”解决过程及方法

    Java中的`java.util.concurrent`包提供了`BlockingQueue`接口,可以方便地实现生产者-消费者模型。生产者将产品放入队列,消费者从队列中取出产品,队列的大小限制了可以同时存储的产品数量,从而实现自动同步。 5...

    生产者-消费者.zip

    在项目的"生产者-消费者"代码中,可以预见到它将展示如何创建`BlockingQueue`实例,然后在生产者线程中调用`put`方法向队列添加元素,在消费者线程中调用`take`方法取出元素。同时,可能还会有异常处理和中断机制,...

    生产者-消费者多线程处理

    在Java中,可以使用`BlockingQueue`接口来实现生产者-消费者模式,它已经内置了线程安全的队列操作。生产者可以使用`offer()`方法添加元素,消费者则用`take()`方法取出元素,这两个方法会自动处理等待和唤醒操作。 ...

    JAVA_生产者-消费者

    2. **BlockingQueue接口**:Java并发包`java.util.concurrent`中的`BlockingQueue`接口为生产者-消费者问题提供了一种更为高级且易用的解决方案。`BlockingQueue`实现了线程安全的队列操作,如`put()`(添加元素)和...

    Java多线程 生产者-消费者模式

    `BlockingQueue`接口是最常用的实现方式,它提供了线程安全的数据结构,可以用来作为生产者和消费者之间的缓冲区。例如,我们可以使用`ArrayBlockingQueue`、`LinkedBlockingQueue`等具体实现。 下面通过一个简单的...

    多线程间通信:多生产者-多消费者实例

    `BlockingQueue`是一种线程安全的数据结构,它实现了生产者和消费者之间的阻塞等待。当队列满时,生产者会阻塞直到有空间可以插入;同样,当队列为空时,消费者也会阻塞等待新的数据。 下面是一个简单的多生产者-多...

    并发控制-生产者-消费者问题

    在计算机科学中,"并发控制-生产者-消费者问题"是一个经典的多线程同步问题,它涉及到了进程通信和资源管理。这个问题的核心在于确保生产者(生成数据的线程)和消费者(消耗数据的线程)能够有效地共享一个有限...

    线程----BlockingQueue

    这种特性使得`BlockingQueue`非常适合用于生产者-消费者模式的场景。 #### 2. BlockingQueue的常用方法 `BlockingQueue`接口定义了一系列的方法来支持线程安全的操作: - **add(anObject)**: 将`anObject`添加到`...

    Java多线程实现生产者消费者

    本示例中的“生产者-消费者”模型是一种经典的多线程问题,它模拟了实际生产环境中的资源分配与消耗过程。下面我们将详细探讨如何在Java中实现这个模型。 首先,我们要理解生产者-消费者模型的基本概念。在这个模型...

    基于JAVA线程机制研究生产者-消费者问题.pdf

    这通常涉及到使用同步队列(如BlockingQueue)等数据结构来控制生产者何时产生数据,消费者何时消费数据。 BlockingQueue是一种线程安全的队列,提供了在生产者和消费者之间阻塞或等待的机制。当队列满了时,生产者...

    基于JAVA线程机制研究生产者-消费者问题.zip

    2. BlockingQueue:Java并发包(java.util.concurrent)中的BlockingQueue接口提供了一种更安全、更高效的方式来处理生产者-消费者问题。它是一个线程安全的数据结构,内部已经实现了线程同步和等待通知机制。生产者...

    【IT十八掌徐培成】Java基础第08天-04.多线程-生产者-消费者.zip

    5. ** 线程安全与同步**:`BlockingQueue`提供了内置的线程同步机制,因此生产者和消费者在操作队列时不会出现数据不一致的情况。这比使用传统的`synchronized`关键字或者`wait()`/`notify()`来手动管理线程同步更...

    java多线程实现生产者和消费者

    `BlockingQueue`接口提供了线程安全的队列,自动处理了等待和唤醒操作,是实现生产者-消费者模型的一种高效方式。 4. **条件变量**:`wait()`, `notify()`和`notifyAll()`是基于条件变量的,它们可以使得线程在特定...

    Java-concurrent-collections-concurrenthashmap-blockingqueue.pdf

    Java 并发集合:ConcurrentHashMap 和 ...Java 并发集合(ConcurrentHashMap 和 BlockingQueue)提供了高效的并发操作和线程安全机制,广泛应用于多种场景,例如多线程编程、数据存储和访问、生产者-消费者模式等。

    多线程_生产者与消费者模式示例

    线程池可以配合生产者消费者模式,例如通过提交任务到线程池来实现生产者,线程池中的工作线程充当消费者角色。 在使用生产者消费者模式时,需要注意以下几点: - **线程安全**:确保所有的操作都是线程安全的,...

    生产者消费者

    在Java中,`BlockingQueue`接口是实现生产者消费者模式的理想选择。`BlockingQueue`提供了线程安全的队列操作,并且内置了阻塞机制。当队列满时,`put()`方法会使得生产者线程自动阻塞,直至队列有空位;当队列空时...

    java模拟生产者和消费者问题

    在Java中,可以通过多种方式实现生产者-消费者模型,包括但不限于使用`wait()`和`notify()`方法、`BlockingQueue`接口、`Semaphore`类以及`ReentrantLock`和`Condition`组合等。 #### 使用`wait()`和`notify()` 这...

    Java并发编程--BlockingQueue.docx

    在生产者-消费者场景下,BlockingQueue 能够确保生产者线程在队列满时不会过度生产,而消费者线程在队列为空时也不会过度消耗资源。示例代码展示了如何创建生产者和消费者线程,它们共享同一个 BlockingQueue 实例,...

    java 编写的生产者与消费者问题

    这个库提供了多种工具类,如Semaphore(信号量)、BlockingQueue(阻塞队列)和Condition(条件变量),这些都可以用来实现生产者-消费者模型。 1. **BlockingQueue**: 阻塞队列是一种特殊的队列,它具有线程安全的...

Global site tag (gtag.js) - Google Analytics