首页 > 编程笔记 > Java笔记 阅读:11

Java BlockingQueue和BlockingDeque的区别(非常详细)

BlockingQueue 和 BlockingDeque 都是 JUC(java.util.concurrent包)中的接口,用于在多线程环境中处理元素的集合,允许线程安全地从队列中添加和移除元素。

BlockingQueue 和 BlockingDeque 在功能上有很多相似之处,主要的区别在于它们的数据结构特性和操作方法。

Java BlockingQueue

BlockingQueue 代表一个支持阻塞操作的线程安全队列,它扩展了 Queue 接口,增加了能够阻塞或等待队列变为非空时取出元素,以及等待空间变得可用时存入元素的操作。

BlockingQueue 支持的操作如下表所示:

方法 描述
add(e) 在队列的尾部插入指定的元素,成功时返回 true;如果没有可用空间,则抛出 IllegalStateException
offer(e) 在队列的尾部插入指定的元素,成功时返回 true;如果没有可用空间,则返回 false
offer(e, time, unit) 将元素插入队列的尾部,等待指定的时间以让空间变得可用;时间单位由第三个参数指定
put(e) 将元素插入队列的尾部,如果队列满,则等待空间变得可用
remove() 移除队列的头部元素,如果队列为空,则抛出 NoSuchElementException
poll() 移除并返回队列头部的元素,如果队列为空,则返回 null
poll(time, unit) 移除并返回队列头部的元素,如果队列为空,等待指定的时间以让元素变得可用,时间单位由第二个参数指定
take() 移除并返回队列头部的元素,如果队列为空,则等待直到有元素可用
element() 返回队列头部的元素,如果队列为空,则抛出 NoSuchElementException
peek() 返回队列头部的元素,如果队列为空,则返回 null

BlockingQueue 常用于生产者-消费者场景,其中,生产者和消费者可能运行在不同的线程中。生产者将对象放入队列,消费者则从队列中取出对象。当队列为空时,消费者线程会被阻塞,直到有元素可以取出。同样,如果队列是有界的,生产者线程在队列满时会被阻塞,直到队列中有空间可用以插入新元素。

BlockingQueue 只是一个接口,JUC 提供了多种具体实现,常用的几种如下:

Java BlockingDeque

BlockingDeque 代表了一个双端队列(Deque,即 Double-Ended Queue),同时支持阻塞操作。

BlockingDeque 继承自 BlockingQueue,在 BlockingQueue 的基础上,增加了能够从队列的双端插入和移除元素的能力。这种双端队列支持同时作为标准队列(FIFO)和栈 [LIFO(Last In First Out,后进先出)] 使用。

BlockingDeque 的主要特点和功能如下。
BlockingDeque 提供的主要方法如下表所示:

方法 描述
addFirst(e) / offerFirst(e) 将指定元素插入双端队列的头部,队列已满时,直接抛出异常
addLast(e) / offerLast(e) 将指定元素插入双端队列的尾部,队列已满时,直接抛出异常
putFirst(e) / offerFirst(e, time, unit) 将指定元素插入双端队列的头部,队列已满时,进行阻塞等待
putLast(e) / offerLast(e, time, unit) 将指定元素插入双端队列的尾部,队列已满时,进行阻塞等待
removeFirst() / pollFirst() 移除并返回双端队列的第一个元素,队列为空时,直接抛出异常
removeLast() / pollLast() 移除并返回双端队列的最后一个元素,队列为空时,直接抛出异常
takeFirst() / pollFirst(time, unit) 移除并返回双端队列的第一个元素,队列为空时,进行阻塞等待
takeLast() / pollLast(time, unit) 移除并返回双端队列的最后一个元素,队列为空时,进行阻塞等待
getFirst() / peekFirst() 返回双端队列的第一个元素
getLast() / peekLast() 返回双端队列的最后一个元素

BlockingDeque 扩展了 BlockingQueue,它继承了 BlockingQueue 的所有功能,同时增加了对双端操作的支持,这种结构非常适用于需要双端访问的场景,如工作窃取算法和某些并发编程模式。JUC 也提供了 BlockingDeque 的具体实现,例如 LinkedBlockingDeque(它是一个基于链表结构的可选有界 BlockingDeque)。

BlockingQueue和BlockingDeque的区别

BlockingDeque 和 BlockingQueue 的区别主要有以下几个方面:
在并发编程中,我们选择哪一种队列取决于具体的需求,例如需要单向队列还是双端队列、大小限制要求、插入和移除操作的公平性要求、排序要求等。

相关文章