首页 > 其他分享 >JUC提供了哪些阻塞队列

JUC提供了哪些阻塞队列

时间:2023-03-19 15:33:35浏览次数:57  
标签:JUC 队列 抛出 元素 阻塞 无界 线程

阻塞队列的处理方法

阻塞队列实现了 BlockingQueue 接口,并且有多组处理方法。

抛出异常

  • add方式是往队列里面添加元素,如果队里队列满了,会抛出异常
  • remove方法是删除元素,如果队列里面的不够删除了则抛出异常
  • element 方法是返回队列的头部节点,但是并不删除。如果用这个方法去操作一个空队列,会抛出和前面 remove 方法一样的异常:NoSuchElementException

返回结果但不抛出异常

  • offer 方法用来插入一个元素,并用返回值来提示插入是否成功。如果添加成功会返回 true,而如果队列已经满了,此时继续调用 offer 方法的话,它不会抛出异常,只会返回一个错误提示:false。
  • poll 方法表示移除并返回队列的头节点。如果当队列里面是空的,便会返回 null 作为提示。正因如此,是不允许往队列中插入 null 的,否则没有办法区分返回的 null 是一个提示还是一个真正的元素。
  • peek 方法返回队列的头元素但并不删除。如果队列里面是空的,它便会返回 null 作为提示。

阻塞

  • put 方法的作用是插入元素。如果队列已满就无法继续插入,这时它既不会立刻返回 false 也不会抛出异常,而是让插入的线程陷入阻塞状态,直到队列里有了空闲空间,此时队列就会让之前的线程解除阻塞状态,并把刚才那个元素添加进去。
  • take 方法的作用是获取并移除队列的头结点。通常在队列里有数据的时候会正常取出数据并删除;但是如果执行 take 的时候队列里无数据,则阻塞,直到队列里有数据;一旦队列里有数据了,就会立刻解除阻塞状态,并且取到数据。

抛出异常:add(e) 、remove()、element()
返回结果但不抛出异常:offer(e) 、poll()、peek()
阻塞:put(e) 、take()

JDK 8 中提供了七个阻塞队列

  • ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
  • LinkedBlockingQueue :一个由链表结构组成的无界阻塞队列。
  • PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
  • DelayQueue:一个使用优先级队列实现的无界阻塞队列。
  • SynchronousQueue:一个不存储元素的阻塞队列。
  • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
  • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

ArrayBlockingQueue

一个由数组结构组成的有界阻塞队列。初始时就要指定大小,内部用数组存储元素,利用ReentrantLock实现线程安全。初始创建指定容量后,不能再扩容。ArrayBlockingQueue采用全部锁,锁的粒度较大。

ConcurrentLinkedQueue内部也是由单向链表的方式实现,默认存在一个哨兵节点,它是线程安全的无界非阻塞队列,与BlockingQueue不同的是,ConcurrentLinkedQueue通过CAS方式实现线程安全。

LinkedBlockingQueue

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

如果不指定它的初始容量,则默认容量就是整形的最大值Integer.MAX_VALUE,由于容量非常大,LinkedBlockingQueue 也被称作无界队列。

SynchronousQueue

SynchronousQueue 最大的不同之处在于,它的容量为 0,所以没有一个地方来暂存元素,导致每次取数据都要先阻塞,直到有数据被放入;同理,每次放数据的时候也会阻塞,直到有消费者来取。需要注意的是,SynchronousQueue 的容量不是 1 而是 0,因为 SynchronousQueue 不需要去持有元素,它所做的就是直接传递(direct handoff)。由于每当需要传递的时候,SynchronousQueue 会把元素直接从生产者传给消费者,在此期间并不需要做存储,所以如果运用得当,它的效率是很高的。

SynchronousQueue 的 peek 方法永远返回 null

PriorityBlockingQueue

PriorityBlockingQueue 是一个支持优先级的无界阻塞队列,可以通过自定义类实现 compareTo() 方法来指定元素排序规则,或者初始化时通过构造器参数 Comparator 来指定排序规则。同时,插入队列的对象必须是可比较大小的,也就是 Comparable 的,否则会抛出 ClassCastException 异常。

DelayQueue

DelayQueue是一个无界阻塞延迟队列,具有“延迟”的功能。我们可以设定让队列中的任务延迟多久之后执行,比如 10 秒钟之后执行,这在例如“30 分钟后未付款自动取消订单”等需要延迟执行的场景中被大量使用。它是无界队列,放入的元素必须实现 Delayed 接口,而 Delayed 接口又继承了 Comparable 接口,所以自然就拥有了比较和排序的能力。

ConcurrentLinkedQueue

ConcurrentLinkedQueue并没有直接继承BlockingQueue,而是实现的Queue接口,少了take和put这两个阻塞方法。ConcurrentLinkedQueue内部也是由单向链表的方式实现,它是线程安全的无界非阻塞队列,与BlockingQueue不同的是,ConcurrentLinkedQueue通过CAS方式实现线程安全。

ConcurrentLinkedQueue 使用 CAS 非阻塞算法 + 不停重试,来实现线程安全,适合用在不需要阻塞功能,且并发不是特别剧烈的场景。

 

参考:

 

标签:JUC,队列,抛出,元素,阻塞,无界,线程
From: https://www.cnblogs.com/xfeiyun/p/17233341.html

相关文章

  • 说说对AQS(AbstractQueuedSynchronizer)队列同步器的理解
    AQS是构建锁或者其他同步组件的基础框架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等),包含了实现同步器的细节(获取同步状态、FIFO同步队列)。AQS的主要使用......
  • 优先队列(PriorityQueue)常用方法及简单案例
    1前言PriorityQueue是一种特殊的队列,满足队列的“队尾进、队头出”条件,但是每次插入或删除元素后,都对队列进行调整,使得队列始终构成最小堆(或最大堆)。具体调整如下:插入......
  • 【RabbitMQ消息中间件】11.持久化和非持久化队列
    上一篇介绍并搭建了Spring-Rabbit工程,并且创建了一个名为MyQueue的队列。下面补充一个有关持久化和非持久化队列的知识点。登录RabbitMQ的图形化管理界......
  • 3.7 队列的表示和实现
    3.5队列的表示和操作实现相关术语队列(Queue)是仅在表尾进行插入操作,在表头进行删除操作的线性表。表尾及a(((((n)))))端,称为队尾;表头即a(((((1)))))端称为......
  • 3.8 队列的顺序表示和实现
    3.5.2队列的顺序表示和实现队列的物理存储可以用顺序结构,也可用链式存储结构,相应地队列的存储方式也分为两种,即顺序队列和链式队列、队列的顺序表示——————......
  • 3.9 队列的链式表示和实现
    3.5.3队列的链式表示和实现适用于用户无法估计所用队列的长度,则适宜采用该类型的队列链式队列的结构图如下所示链队列的类型定义//这里是定义是每个节点类型t......
  • 3.1 栈和队列定义和特点
    栈和队列是限定插入和删除的只能在表“端点”进行的线性表普通线性表的插入和删除操作栈的定义和特点栈(stack)是一个特殊的线性表,是限定的仅在一端(通常是表尾)进行插......
  • 线程池中阻塞队列的作用?为什么是先添加列队而不是先创建最大线程?
    线程池中阻塞队列的作用:1.⼀般的队列只能保证作为⼀个有限⻓度的缓冲区,如果超出了缓冲⻓度,就⽆法保留当前的任务了,阻塞队列通过阻塞可以保留住当前想要继续⼊队的任务。2.......
  • 测试JUC安全类型的集合
    packageedu.wtbu;importjava.util.concurrent.CopyOnWriteArrayList;//测试JUC安全类型的集合publicclassDemo09{publicstaticvoidmain(String[]args){......
  • 【LeetCode贪心#08】根据身高重建队列(还是涉及处理两个维度的信息)
    根据身高重建队列力扣题目链接(opensnewwindow)假设有打乱顺序的一群人站成一个队列,数组people表示队列中一些人的属性(不一定按顺序)。每个people[i]=[hi,ki]表......