BlockingQueue介绍

Stella981
• 阅读 715

几种类型的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);

    }

}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
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
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java并发数据结构
一.BlockingDeque阻塞双端队列(线程安全):注意ArrayDeque和LinkedList仅仅扩展了Deque,是非阻塞类型的双端队列。BlockingQueue单向队列,其内部基于ReentrantLockCondition来控制同步和"阻塞"/"唤醒"的时
Wesley13 Wesley13
3年前
04.JUC 集合
基本概念LinkedBlockingQueue是一个用链表实现的有界阻塞队列。LinkedBlockingQueue按照先进先出的原则对元素进行排序。LinkedBlockingQueue采用了双锁、双条件队列来提高读写效率。内部构造LinkedBlockingQueue内部维
Wesley13 Wesley13
3年前
Java多线程之线程安全队列Queue
在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列。Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。注:什么叫线程安全?这个首先要明确。
Stella981 Stella981
3年前
PriorityBlockingQueue 介绍
PriorityBlockingQueue是一个基于优先级堆的无界的并发安全的优先级队列(FIFO),队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的Comparator进行排序,具体取决于所使用的构造方法。实现原理PriorityBlockingQueue通过使用堆这种数据结构实现将队列中的元素按照某种排序规则进行排序,从而改变先进先
Wesley13 Wesley13
3年前
JAVA线程15
一、阻塞队列1\.概述阻塞队列是Java5线程新特征中的内容,Java定义了阻塞队列的接口java.util.concurrent.BlockingQueue。阻塞队列是一个指定长度的队列,如果队列满了,添加新元素的操作会被阻塞等待,直到有空位为止。同样,当队列为空时候,请求队列元素的操作同样会阻塞等待,直到有可用元
Stella981 Stella981
3年前
Netty学习笔记1:5种IO模型
1阻塞IO模型从字面来理解,就是调用时可能被阻塞,什么叫阻塞,要知道一个进程有N种状态,学过OS都知道如果阻塞,就会把当前进程放在某个条件的阻塞队列里。直到条件满足了,才会转移此进程进入就绪队列。当然,就绪队列还有个优先级的概念,就不扯远了。阻塞IO.1)调用API,比如 r
Stella981 Stella981
3年前
BlockingQueue(阻塞队列)详解
注意:该随笔内容完全引自http://wsmajunfeng.iteye.com/blog/1629354,写的很好,非常感谢,复制过来算是个积累,怕以后找不到。一.前言  在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程
Wesley13 Wesley13
3年前
Java并发 阻塞队列
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加操作支持阻塞地插入和移除方法。支持阻塞插入的方法是指当队列满时会阻塞插入元素的线程,直到队列不满;支持阻塞移除的方法是指当队列为空时获取元素的线程无法继续获取元素直到队列不空。可以发现阻塞队列非常适合消费者和生产者场景下进行使用,生产者生产数据就是向阻塞队列中插入元素,消费者消