Java ~ Collection/Executor ~ BlockingDeque【总结】

33 篇文章 0 订阅
17 篇文章 0 订阅

一 概述


 简介

    BlockingDeque(阻塞双端队列)接口(下文简称阻塞双端队列)是BlockingQueue(阻塞队列)接口的子接口,在其的基础上进行了功能性的加强,新增了可在队列的两端进行插入/移除/检查操作的方法定义,就如同Deque(双端队列)接口对Queue(队列)接口做的那样。事实上,阻塞双端队列也确实同时是Deque(双端队列)接口的子接口,因此其新增的方法定义中有一部分是从Deque(双端队列)接口直接继承得来的,该知识点的详细内容会在下文详述。

    阻塞双端队列是线程安全的,即实现类无论采用了何种实现方式,都必须保证线程安全,该定义继承自BlockingQueue(阻塞队列)接口。该定义意味着阻塞双端队列实现类的绝大多数方法实现都会是原子性的(否则无法保证线程安全),但对于批量方法就并非如此。例如addAll()、containsAll()及removeAll()等方法完全可以在底层循环调用add()、contains()及remove()方法来达到目的,因此在整体执行中可能伴随着并发。总的来说,即只要求单方法原子性执行,而批量方法除非特别指定,否则没有原子性执行的要求。因此,对于批量方法部分成功部分失败的情况是可以被接受的。例如在addAll()方法执行的过程中有元素抛出异常而导致后续元素添加失败,但前期元素添加成功的场景。

    阻塞双端队列不允许存null值,该定义继承自BlockingQueue(阻塞队列)接口。接口规定一旦尝试在阻塞双端队列中存null值时必须抛出空异常,这是较为少见的,因为一般来说接口都不会对null值做强制的定义,而是交给子类自身去决定。阻塞双端队列之所以强制不允许存null值是因为null已经被用来作为标志位使用,具体原因与“方法的不同形式”有关,该知识点的详细内容会在下文详述。

    阻塞双端队列虽然与BlockingQueue(阻塞队列)接口一样都被纳入Executor(执行器)框架的范畴,但同时也是Collection(集)框架的成员。

 方法的不同形式

    方法的不同形式实际上是BlockingQueue(阻塞队列)接口的定义,阻塞双端队列只是继承了这个定义而已。所谓方法的不同形式,是指方法在保证自身核心操作不变的情况下实现了多种不同的回应形式来应对不同场景下的使用要求。例如对于插入,当容量不足时,有些场景希望在失败时抛出异常;而有些场景则希望能直接返回失败的标记值;而有些场景又希望可以等待直至有可用空间后成功新增为止…正因如此,BlockingQueue(阻塞队列)接口特意提供了四种不同的形式风格以满足不同场景下的使用需求,因此一个方法最多(并非所有方法都实现了四种形式)可能有四种不同回应形式。具体四种回应形式如下:

  • 异常:当不满足操作条件时直接抛出异常;
  • 特殊值:当不满足操作条件时直接返回失败标记值。例如之所以不允许存null值就是因为null被作为了获取操作失败时的标记值;
  • 阻塞(无限等待):当不满足操作条件时无限等待,直至满足操作条件后执行;
  • 超时(有限等待):当不满足操作条件时有限等待,如果在指定等待时间之前直至满足操作条件则执行;否则返回失败标记值。

二 方法


    阻塞双端队列在BlockingQueue(阻塞队列)接口的基础上新增了诸多在队列两端进行插入/移除/检查等待操作的方法定义,这些有些是阻塞双端队列自身定义的,有些则继承自父接口Deque(双端队列)。对于阻塞双端队列自身的方法定义会在下文重点标注,你会发现这些方法定义都是“阻塞”与“超时”形式,因为这两种形式是父接口BlockingQueue(阻塞队列)新定义的。而其它形式及类型的方法定义大都继承自父接口Deque(双端队列)。

    注意:下文中不会出现BlockingQueue(阻塞队列)接口定义的方法,有意者请自行查询。

 插入/放置

    插入/放置是阻塞队列两大最核心也是最常用的方法之一,用于向阻塞队列的尾部插入指定元素。阻塞双端队列/双端队列增强了该功能,新增了“向阻塞队列的头部插入指定元素”的方法定义,并对“向阻塞队列的尾部插入指定元素”的方法定义进行了封装(即为了保证命名规范定义了功能相同但名称不同的方法)。由于场景的多样性需求,阻塞双端队列/阻塞队列定义了插入/放置方法四种形式的实现以供使用。

  • void addFirst(E e) —— 新增首个 —— 向当前阻塞双端队列的头部插入指定元素。该方法是头部插入/放置方法“异常”形式的实现,当阻塞双端队列存在剩余容量时插入/放置成功;否则抛出非法状态异常。

  • void addLast(E e) —— 新增最后 —— 向当前阻塞双端队列的尾部插入指定元素。该方法是尾部插入/放置方法“异常”形式的实现,当阻塞双端队列存在剩余容量时插入/放置成功;否则抛出非法状态异常。该方法等价于add(E e)方法,但区别该方法没有返回值…事实上也不需要返回值,因为只要没有抛出异常就意味着插入/放置成功。

  • boolean offerFirst(E e) —— 提供首个 —— 向当前阻塞双端队列的头部插入指定元素。该方法是头部插入/放置方法“特殊值”形式的实现,当阻塞双端队列存在剩余容量时插入/放置成功并返回true;否则返回false。

  • boolean offerLast(E e) —— 提供最后 —— 向当前阻塞双端队列的尾部插入指定元素。该方法是尾部插入/放置方法“特殊值”形式的实现,当阻塞双端队列存在剩余容量时插入/放置成功并返回true;否则返回false。该方法等价于offer(E e)方法。

  • void putFirst(E e) throws InterruptedException —— 放置首个 —— 向当前阻塞双端队列的头部插入指定元素。该方法是头部插入/放置方法“阻塞”形式的实现,当阻塞双端队列存在剩余容量时插入/放置成功;否则等待至存在剩余容量为止。该方法由阻塞双端队列自身定义。

  • void putLast(E e) throws InterruptedException —— 放置最后 —— 向当前阻塞双端队列的尾部插入指定元素。该方法是尾部插入/放置方法“阻塞”形式的实现,当阻塞双端队列存在剩余容量时插入/放置成功;否则等待至存在剩余容量为止。该方法由阻塞双端队列自身定义,等价于put(E e)方法。

  • boolean offerFirst(E e, long timeout, TimeUnit unit) throws InterruptedException —— 提供首个 —— 向当前阻塞双端队列的头部插入指定元素。该方法是头部插入/放置方法“超时”形式的实现,当阻塞双端队列存在剩余容量时插入/放置成功并返回true;否则在指定等待时间内等待至存在剩余容量,超出指定等待时间则返回false。该方法由阻塞双端队列自身定义。

  • boolean offerLast(E e, long timeout, TimeUnit unit) throws InterruptedException —— 提供最后 —— 向当前阻塞双端队列的尾部插入指定元素。该方法是尾部插入/放置方法“超时”形式的实现,当阻塞双端队列存在剩余容量时插入/放置成功并返回true;否则在指定等待时间内等待至存在剩余容量,超出指定等待时间则返回false。该方法由阻塞双端队列自身定义,等价于offer(E e, long timeout, TimeUnit unit)方法。

 移除/拿取

    移除/拿取是阻塞队列两大最核心也是最常用的方法之一,用于从阻塞队列的头部移除并获取元素。阻塞双端队列/双端队列增强了该功能,新增了“从阻塞队列的尾部移除并获取元素”的方法定义,并对“从阻塞队列的头部移除并获取元素”的方法定义进行了封装。移除/拿取方法同样有四种形式的实现。

  • E removeFirst() —— 移除首个 —— 从当前阻塞双端队列的头部移除并获取元素。该方法是头部移除/拿取方法中“异常”形式的实现,当阻塞双端队列存在元素时移除/拿取并返回头元素;否则抛出无如此元素异常。该方法等价于remove()方法。

  • E removeLast() —— 移除最后 —— 从当前阻塞双端队列的尾部移除并获取元素。该方法是尾部移除/拿取方法中“异常”形式的实现,当阻塞双端队列存在元素时移除/拿取并返回尾元素;否则抛出无如此元素异常。

  • E pollFirst() —— 轮询首个 —— 从当前阻塞双端队列的头部移除并获取元素。该方法是头部移除/拿取方法中“特殊值”形式的实现,当阻塞双端队列存在元素时移除/拿取并返回头元素;否则返回null。该方法等价于poll()方法。

  • E pollLast() —— 轮询最后 —— 从当前阻塞双端队列的尾部移除并获取元素。该方法是尾部移除/拿取方法中“特殊值”形式的实现,当阻塞双端队列存在元素时移除/拿取并返回尾元素;否则返回null。

  • E takeFirst() throws InterruptedException —— 拿取首个 —— 从当前阻塞双端队列的头部移除并获取元素。该方法是头部移除/拿取方法中“阻塞”形式的实现,当阻塞双端队列存在元素时移除/拿取并返回头元素;否则等待至存在元素。该方法由阻塞双端队列自身定义,等价于take()方法。

  • E takeLast() throws InterruptedException —— 拿取最后 —— 从当前阻塞双端队列的尾部移除并获取元素。该方法是尾部移除/拿取方法中“阻塞”形式的实现,当阻塞双端队列存在元素时移除/拿取并返回尾元素;否则等待至存在元素。该方法由阻塞双端队列自身定义。

  • E pollFirst(long timeout, TimeUnit unit) throws InterruptedException —— 轮询首个 —— 从当前阻塞双端队列的头部移除并获取元素。该方法是头部移除/拿取方法中“超时”形式的实现,当阻塞双端队列存在元素时移除/拿取并返回头元素;否则在指定等待时间内等待至存在元素,超出指定等待时间则返回null。该方法由阻塞双端队列自身定义,等价于poll(long timeout, TimeUnit unit)方法。

  • E pollLast(long timeout, TimeUnit unit) throws InterruptedException —— 轮询最后 —— 从当前阻塞双端队列的尾部移除并获取元素。该方法是尾部移除/拿取方法中“超时”形式的实现,当阻塞双端队列存在元素时移除/拿取并返回尾元素;否则在指定等待时间内等待至存在元素,超出指定等待时间则返回null。该方法由阻塞双端队列自身定义。

 检查

    检查也是阻塞队列的常用方法之一,用于从阻塞队列的头部获取元素,但并不会将元素从阻塞队列中移除,属于移除/拿取方法的阉割版。双端队列增强了该功能,新增了“从阻塞队列的尾部获取元素”的方法定义,并对“从阻塞队列的头部获取元素”的方法定义进行了封装。检查方法同样具备多形式的实现,但只有“异常”与“特殊值”两种。

  • E getFirst() —— 获取首个 —— 从当前阻塞双端队列的头部获取元素。该方法是头部检查方法中“异常”形式的实现,当阻塞双端队列存在元素时返回头元素;否则抛出无如此元素异常。该方法等价于element()方法。

  • E getLast() —— 获取最后 —— 从当前阻塞双端队列的尾部获取元素。该方法是尾部移除/拿取方法中“异常”形式的实现,当阻塞双端队列存在元素时返回尾元素;否则抛出无如此元素异常。

  • E peekFirst() —— 窥视首个 —— 从当前阻塞双端队列的头部获取元素。该方法是头部检查方法中“特殊值”形式的实现,当阻塞双端队列存在元素时返回头元素;否则返回null。该方法等价于peek()方法。

  • E peekLast() —— 窥视最后 —— 从当前阻塞双端队列的尾部获取元素。该方法是尾部检查方法中“特殊值”形式的实现,当阻塞双端队列存在元素时返回尾元素;否则返回null。

 内部移除

    内部移除的原始方法定义源自Collection(集)接口的remove(Object o)方法,用于将集中指定元素的首个单例(迭代器顺序)移除。由于指定元素可能处于集中的任意位置(不一定是头/尾),因此被称为内部移除。内部移除在队列中并不是常用的方法:一是其不符合队列FIFO的数据结构;二是各类队列为了提高性能可能会使用各种优化策略,而remove(Object o)方法往往无法适配这些策略,导致性能较/极差。双端队列增强了内部移除功能,在“从阻塞队列中移除指定元素的首个单例”的方法定义基础上新增了“从阻塞队列中移除指定元素的最后单例”的方法定义,并对“从阻塞队列中移除指定元素的首个单例”的方法定义进行了封装。

  • boolean removeFirstOccurrence(Object o) —— 移除首次出现 —— 从当前阻塞双端队列中移除指定元素的首个单例,移除成功返回true;否则返回false。该方法等价于remove(Object o)方法。
  • boolean removeLastOccurrence(Object o) —— 移除最后出现 —— 从当前阻塞双端队列中移除指定元素的最后单例,移除成功返回true;否则返回false。

 堆栈

    堆栈功能是Deque(双端队列)接口为了模拟堆栈适配Stack(堆栈)类而新增的方法定义,而阻塞双端队列继承了这些定义。

  • void push(E e) —— 推送 —— 向当前阻塞双端队列的头部插入指定元素。如果存在剩余空间则插入成功,否则抛出非法状态异常。该方法等价于addFirst(E e)方法。

  • void pop(E e) —— 弹出 —— 从当前双端队列的头部移除并获取元素。如果存在元素则返回头元素,否则抛出无如此元素异常。该方法等价于removeFirst()方法。

三 相关系列


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

说淑人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值