ArrayBlockingQueue和LinkedBlockingQueue的使用

转载 2016年06月02日 11:16:34

BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会阻塞。

 

ArrayBlockingQueue是一个由数组支持的有界阻塞队列。在读写操作上都需要锁住整个容器,因此吞吐量与一般的实现是相似的,适合于实现“生产者消费者”模式。

 

基于链表的阻塞队列,同ArrayListBlockingQueue类似,其内部也维持着一个数据缓冲队列(该队列由一个链表构成),当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue可以通过构造函数指定该值),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。而LinkedBlockingQueue之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。

 

ArrayBlockingQueue和LinkedBlockingQueue的区别:

1. 队列中锁的实现不同

    ArrayBlockingQueue实现的队列中的锁是没有分离的,即生产和消费用的是同一个锁;

    LinkedBlockingQueue实现的队列中的锁是分离的,即生产用的是putLock,消费是takeLock

2. 在生产或消费时操作不同

    ArrayBlockingQueue实现的队列中在生产和消费的时候,是直接将枚举对象插入或移除的;

    LinkedBlockingQueue实现的队列中在生产和消费的时候,需要把枚举对象转换为Node<E>进行插入或移除,会影响性能

3. 队列大小初始化方式不同

    ArrayBlockingQueue实现的队列中必须指定队列的大小;

    LinkedBlockingQueue实现的队列中可以不指定队列的大小,但是默认是Integer.MAX_VALUE


package com.guhui.test;

import java.io.*;
import java.util.*;
import java.util.concurrent.*;

/**
 * @version 1.01 2012-01-26
 * @author Cay Horstmann
 */
public class BlockingQueueTest
{
   public static void main(String[] args)
   {
      Scanner in = new Scanner(System.in);
      System.out.print("Enter base directory (e.g. /usr/local/jdk1.6.0/src): ");
      String directory = in.nextLine();
      System.out.print("Enter keyword (e.g. volatile): ");
      String keyword = in.nextLine();

      final int FILE_QUEUE_SIZE = 10;
      final int SEARCH_THREADS = 100;

      BlockingQueue<File> queue = new ArrayBlockingQueue<>(FILE_QUEUE_SIZE);

      FileEnumerationTask enumerator = new FileEnumerationTask(queue, new File(directory));
      new Thread(enumerator).start();
      for (int i = 1; i <= SEARCH_THREADS; i++)
         new Thread(new SearchTask(queue, keyword)).start();
   }
}

/**
 * This task enumerates all files in a directory and its subdirectories.
 */
class FileEnumerationTask implements Runnable
{
   public static File DUMMY = new File("");
   private BlockingQueue<File> queue;
   private File startingDirectory;

   /**
    * Constructs a FileEnumerationTask.
    * @param queue the blocking queue to which the enumerated files are added
    * @param startingDirectory the directory in which to start the enumeration
    */
   public FileEnumerationTask(BlockingQueue<File> queue, File startingDirectory)
   {
      this.queue = queue;
      this.startingDirectory = startingDirectory;
   }

   public void run()
   {
      try
      {
         enumerate(startingDirectory);
         queue.put(DUMMY);
      }
      catch (InterruptedException e)
      {
      }
   }

   /**
    * Recursively enumerates all files in a given directory and its subdirectories.
    * @param directory the directory in which to start
    */
   public void enumerate(File directory) throws InterruptedException
   {
      File[] files = directory.listFiles();
      for (File file : files)
      {
         if (file.isDirectory()) enumerate(file);
         else queue.put(file);
      }
   }
}

/**
 * This task searches files for a given keyword.
 */
class SearchTask implements Runnable
{
   private BlockingQueue<File> queue;
   private String keyword;

   /**
    * Constructs a SearchTask.
    * @param queue the queue from which to take files
    * @param keyword the keyword to look for
    */
   public SearchTask(BlockingQueue<File> queue, String keyword)
   {
      this.queue = queue;
      this.keyword = keyword;
   }

   public void run()
   {
      try
      {
         boolean done = false;
         while (!done)
         {
            File file = queue.take();
            if (file == FileEnumerationTask.DUMMY)
            {
               queue.put(file);
               done = true;
            }
            else search(file);
         }
      }
      catch (IOException e)
      {
         e.printStackTrace();
      }
      catch (InterruptedException e)
      {
      }
   }

   /**
    * Searches a file for a given keyword and prints all matching lines.
    * @param file the file to search
    */
   public void search(File file) throws IOException
   {
      try (Scanner in = new Scanner(file))
      {
         int lineNumber = 0;
         while (in.hasNextLine())
         {
            lineNumber++;
            String line = in.nextLine();
            if (line.contains(keyword)) 
               System.out.printf("%s:%d:%s%n", file.getPath(), lineNumber, line);
         }
      }
   }
}


来自:http://chenjumin.iteye.com/blog/2182322



ArrayBlockingQueue和LinkedBlockingQueue的区别及使用

BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会...
  • USTC_Zn
  • USTC_Zn
  • 2017年02月04日 16:56
  • 2479

LinkedBlockingQueue的简单使用

LinkedBlockingQueue是线程安全的,实现先进先出顺序执行。也可以执行容量,不设置默认最大为Integer.MAX_VALUE,配合Handler一起使用, 下面贴出我写的一个简单例子...
  • chengxiuhong1
  • chengxiuhong1
  • 2017年06月13日 13:42
  • 455

【Java并发编程】LinkedBlockingQueue的使用(六)

我是小毛驴,一个游戏人,我的梦想是世界和平。原文地址:http://blog.csdn.net/liulongling/article/details/50596624  一、LinkedBlock...
  • liulongling
  • liulongling
  • 2016年01月27日 21:01
  • 5521

深入剖析java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue

【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/77410889 出自【...
  • javazejian
  • javazejian
  • 2017年08月31日 13:40
  • 4557

Java LinkedBlockingQueue和ArrayBlockingQueue分析

LinkedBlockingQueue是一个链表实现的阻塞队列,在链表一头加入元素,如果队列满,就会阻塞,另一头取出元素,如果队列为空,就会阻塞。 LinkedBlockingQueue内部使用R...
  • hongchangfirst
  • hongchangfirst
  • 2014年09月29日 12:09
  • 14422

ArrayBlockingQueue跟LinkedBlockingQueue的区别

1.队列中的锁的实现不同        ArrayBlockingQueue中的锁是没有分离的,即生产和消费用的是同一个锁;        LinkedBlockingQueue中的锁是分离的,即...
  • z69183787
  • z69183787
  • 2015年07月21日 15:32
  • 5001

ArrayBlockingQueue和LinkedBlockingQueue的使用

BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会...
  • xyblog
  • xyblog
  • 2016年06月02日 11:16
  • 740

Java并发编程与技术内幕:ArrayBlockingQueue、LinkedBlockingQueue及SynchronousQueue源码解析

一、BlockingQueue介绍与常用方法 BlockingQueue是一个阻塞队列。在高并发场景是用得非常多的,在线程池中。如果运行线程数目大于核心线程数目时,也会尝试把新加入的线程放到一个...
  • u012129558
  • u012129558
  • 2016年07月08日 11:41
  • 556

ConcurrentLinkedQueue、AraayBlockingQueue、LinkedBlockingQueue 区别及使用场景

三者区别与联系:联系,三者 都是线程安全的。区别,就是 并发 和 阻塞,前者为并发队列,因为采用cas算法,所以能够高并发的处理;后2者采用锁机制,所以是阻塞的。注意点就是前者由于采用cas算法,虽...
  • fz2543122681
  • fz2543122681
  • 2016年10月03日 22:29
  • 1389

源码解析:ArrayBlockingQueue和LinkedBlockingQueue的区别

对于ArrayBlockingQueue和LinkedBlockingQueue已经都只是知道如何使用以及他们各自的特点,没有去看看源码到底驶入实现的!因为ArrayBlockingQueue和Lin...
  • Green_shing
  • Green_shing
  • 2015年06月29日 17:11
  • 1432
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ArrayBlockingQueue和LinkedBlockingQueue的使用
举报原因:
原因补充:

(最多只允许输入30个字)