BlockingQueue介绍

几种类型的BlockingQueue

ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。

LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。

PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。

DelayQueue:一个使用优先级队列实现的无界阻塞队列。

SynchronousQueue:一个不存储元素的阻塞队列。

LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。

LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

ArrayBlockingQueue是一个用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。默认情况下不保证访问者公平的访问队列,所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,当队列可用时,可以按照阻塞的先后顺序访问队列,即先阻塞的生产者线程,可以先往队列里插入元素,先阻塞的消费者线程,可以先从队列里获取元素。通常情况下为了保证公平性会降低吞吐量。

LinkedBlockingQueue是一个用链表实现的有界阻塞队列。此队列的默认和最大长度为Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。

PriorityBlockingQueue是一个支持优先级的无界队列。默认情况下元素采取自然顺序排列,也可以通过比较器comparator来指定元素的排序规则。元素按照升序排列。

DelayQueue是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。我们可以将DelayQueue运用在以下应用场景:

  • 缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。 
  • 定时任务调度。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。

关于BlockingQueue的drainTo方法

int drainTo(Collection<? super E> c,  int maxElements)

  • 从此队列中移除给定数量的可用元素,并将这些元素添加到给定 collection 中。
  • 在向 collection c 中添加元素没有成功时,可能导致在抛出相关异常时,元素会同时在两个 collection 中出现,或者在其中一个 collection 中出现,也可能在两个 collection 中都不出现。
  • 如果试图将一个队列放入自身队列中,则会导致 IllegalArgumentException 异常。
  • 如果正在进行此操作时,正在修改指定的 collection,则此操作行为是不确定的。  

使用技巧

    //先从queue中获取一个对象,如果没有对象线程自动阻塞

    FixERForFixOutgoingValue firstValue = stkRequestQueue.take();

    list.add(firstValue);

    //如果获取到对象了,则一次性获取剩下的全部对象

    stkRequestQueue.drainTo(list);  

BlockingQueue 构建生产消费者模式:

package lands.concurrent; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class BlockingQueueTest {     /**      * @param args      */     public static void main(String[] args) {         //BlockingQueue q = new ArrayBlockingQueue(100); //在构造时需要指定容量         BlockingQueue q = new LinkedBlockingQueue(); //在构造时默认没有上限,但也可以选择指定最大上限         BlockingQueueProducer p1 = new BlockingQueueProducer(q);         BlockingQueueProducer p2 = new BlockingQueueProducer(q);         new Thread(p1).start();         new Thread(p2).start();         BlockingQueueConsumer c1 = new BlockingQueueConsumer(q);         BlockingQueueConsumer c2 = new BlockingQueueConsumer(q);         new Thread(c1).start();         new Thread(c2).start();     } } class BlockingQueueProducer implements Runnable {     private final BlockingQueue queue;     BlockingQueueProducer(BlockingQueue q) {         queue = q;     }     public void run() {         try {             int i = 0;             while (true) {                 i++;                 queue.put(produce(i));                 //System.out.println("remainingCapacity:" + queue.remainingCapacity());             }         } catch (InterruptedException ex) {             ex.printStackTrace();         }     }     String produce(int i) {         //create your wanted object         return i + "";     } } class BlockingQueueConsumer implements Runnable {     private final BlockingQueue queue;     BlockingQueueConsumer(BlockingQueue q) {         queue = q;     }     public void run() {         try {             while (true) {                 consume(queue.take());             }         } catch (InterruptedException ex) {             ex.printStackTrace();         }     }     void consume(Object x) {         //use a object in queue         System.out.println(x);     } }
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java并发数据结构

一.BlockingDeque阻塞双端队列(线程安全):注意ArrayDeque和LinkedList仅仅扩展了Deque,是非阻塞类型的双端队列。BlockingQueue单向队列,其内部基于ReentrantLockCondition来控制同步和"阻塞"/"唤醒"的时

04.JUC 集合

基本概念LinkedBlockingQueue是一个用链表实现的有界阻塞队列。LinkedBlockingQueue按照先进先出的原则对元素进行排序。LinkedBlockingQueue采用了双锁、双条件队列来提高读写效率。内部构造LinkedBlockingQueue内部维

Java多线程之线程安全队列Queue

在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列。Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。注:什么叫线程安全?这个首先要明确。