• Java中常用的七个阻塞队列(一)


    Java中常用的七个阻塞队列介绍第一篇

    在上一篇我们对Java中的队列分类做了简单的介绍。本文咱们主要来聊聊阻塞队列中的七个常用子类。这七个阻塞队列的学习步骤:先看源码,分析完源码之后,我们再来对每个队列进行总结。最后在来个大总结。文章可能有点长,但是,大家耐着性子看完,保证你对这七大阻塞队列有深刻的理解。

    本文主要内容:介绍前三个队列及查看源码总结每个队列的特点

    本文出自凯哥Java(kaigejava)的《凯哥Java并发系列》之《Java并发编程之队列》系列的第二篇:《Java中常用的七个阻塞队列介绍第一篇》

    先来看看这七个子类的类图:

    都是BlockingQueue(阻塞队列的父接口)的子类,而BlockingQueue最终又继承于Collection接口。从而我们可以这么说,阻塞队列是Collection的子类的一个分支也没问题。

    阻塞队列的七个子类:

    ArrayBlockingQueue(下文简称:ABQueue)、LinkedBlockingQueue(下文简称:LBQueue)、PriorityBlockingQueue(下文简称:PBQueue)、DelayQueue(下文简称:DQueue)、SynchronouseQueue(下文简称:SyncQueue)、LinkedTrnsferQueue(下文简称:LTQueue)、LinkedBlockingDeque(下文简称:LBDeque)这个七个。我们来一个一个看。

    ArrayBlockingQueue

    在上面我们知道了阻塞队列是集合的一个子类。我们也知道: Collection<String> c1 = new ArrayList<String>();这个是成立的。那么是不是把ArrayList换成ArrayBlockingQueue也行呢?

    我们测试下:

    发现确实可以的。

    我们来看看arrayBlockingQueue的构造器:

    由三个构造器。代码如下:

    我们看到,其实都调用的是:

    public ArrayBlockingQueue(int capacity, boolean fair) {

    if (capacity <= 0)

    throw new IllegalArgumentException();

    this.items = new Object[capacity];

    lock = new ReentrantLock(fair);

    notEmpty = lock.newCondition();

    notFull = lock.newCondition();

    }

    从代码中我们可以看到:ABQueue底层是数组结构。使用的是ReentrantLock锁。再之前的文章中凯哥(凯哥Java:kaigejava)在讲解ReentrantLock的时候,讲过默认使用的是非公平的。

    所以通过源码分析我们可以对ABQueue得到如下总结:

    ABQueue结论:

    ArrayBlockingQueue:是数据结构的有界的阻塞队列。且默认使用非公平锁,也就是不保证线程公平访问队列的。

    为什么说是有界的呢?因为我们知道数组大小是有边界的。无论你声明的数组多大,最后都一个极限的。存在大小限制,从源码中,来看看向队列中添加数据的方法:

    为什么说默认不保证线程公平呢?因为RLock默认使用的就是非公平机制的。

    如何保证公平呢?在声明的时候,直接设置为true.

    LinkedBlockingQueue

    先来看看构造器:

    和ABQueue类似都是由三个构造器。但是不同的是,LBQueue没有强制输入队列大小的。默认使用的是Integer.MAX_VALUE.那么这个数值是多大呢?2的31次方-1.大概是21亿多。

    从源码中,我们可以看出,last=head=new Node<E>()。从这行代码中,我们可以知道,LBQueue使用的是链表结构。也是使用的RLock锁。

    所以,从源码中,我们可以得到如下总结:

    LBQueue结论:

    LBQueue是使用链表结构的有界阻塞队列。

    为什么说是有界的呢?我们来看看添加的元素的源码:

    需要注意:千万别用默认的。因为默认大小是Integer.MAX_VALUE。java int 类整数的最大值是 2 的 31 次方 - 1 = 2147483648 - 1 = 2147483647。这个数据太大了。如果使用默认的话,也可以理解为无界的。

    PriorityBlockingQueue

    这个队列名字拆开:

    priority:中文的意思是优先的,优先通行权。这个队列支持优先级的。

    来看看构造器:

    如果不传递队列数量。使用默认的。从源码中,我们可以看到默认创建初始的队列大小是11.

    我们来看看添加元素方法的源码:

    从源码中,我们可以到,在添加的时候用了Comparator这个接口。而且在源码中,我们也没看到对队列的大小限制。

    PBQueue总结:

    PBQueue是一个支持优先级的无界阻塞队列。默认情况下元素采用自然顺序升序排列。也可以自定义类来实现comparator接口的compare方法来实现自定义排序规则。或者是在初始化的时候调用public PriorityBlockingQueue(int initialCapacity,Comparator<? super E> comparator) {}这个构造器,支持在初始化的时候传递比较器。PBQueue队列同样使用了RLock,所以不能保证公平性。在添加的时候,不能添加null元素。否则会空指针异常。

    为什么说支持优先级呢?添加元素的源码中使用了Comparator接口。而Comparator默认使用的是字典排序的。

    代码演示

    代码演示,PBQueue使用的默认排序顺序是字典排序升序法。代码如下:

    运行结果:

    下面来演示自定义比较器。

    先来看看自定义的倒序排序器

    在来看看存放和获取后:

    ABQueue、LBQueue、PBQueue比较

    名字 是否有界 数据结构 备注

    ArrayBlockingQueue 有界的 数组 "初始化的时候需要给定队列大小;

    默认非公平的。在初始化的时候可以给定是否使用公平锁"

    LinkedBlockingQueue 有界的 链表 "默认大小事Integer.Max_value.达到21亿不建议使用默认的。"

    PriorityBlockingQueue 无界的 链表 "支持优先级的阻塞队列。

    默认适用自然排序升序规则

    在初始化队列的时候,可以给定比较器的"

  • 相关阅读:
    一个丰富的通知工具类 --第三方开源--NotifyUtil
    RecycleView出现折叠效果--第三方开源--SectionedExpandableGridRecyclerView
    Socket TCP连接相互通信
    InputStream与String,Byte之间互转
    socket调试工具
    可直接导入studio的 android-Ultra-Pull-To-Refresh-master
    纯手写验证码MVC中
    Upload图片-单张
    C#、SQL中的事务
    MVC、控件、一般处理程序中的session and cookie
  • 原文地址:https://www.cnblogs.com/ysd139856/p/12736986.html
Copyright © 2020-2023  润新知