BlockingQueue阻塞队列

Blocking Queue是一个带阻塞功能的队列,当入队列时,若队列已满,则阻塞调 用者;当出队列时,若队列为空,则阻塞调用者。

在Concurrent包中,BlockingQueue是一个接口,有许多个不同的实现类

❑ 普通阻塞队列:基于数组的ArrayBlockingQueue,基于链表的LinkedBlockingQueue

❑ 优先级阻塞队列:PriorityBlockingQueue。

❑ 延时阻塞队列:DelayQueue。

❑ 其他阻塞队列:SynchronousQueue和LinkedTransferQueue。

主要方法有:

1
2
3
4
5
6
7
8
//入队,如果队列满,等待直到队列有空间
void put(E e) throws InterruptedException;
//出队,如果队列空,等待直到队列不为空,返回头部元素
E take() throws InterruptedException;
//入队,如果队列满,最多等待指定的时间,如果超时还是满,返回false
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
//出队,如果队列空,最多等待指定的时间,如果超时还是空,返回null
E poll(long timeout, TimeUnit unit) throws InterruptedException;

 

普通阻塞队列

ArrayBlockingQueue是基于循环数组实现的,有界,创建时需要指定大小,且在运行过程中不会改变

LinkedBlockingQueue是基于单向链表实现的,在创建时可以指定最大长度,也可以不指定,默认是无限的,节点都是动态创建的

 

优先级阻塞队列

普通阻塞队列是先进先出的,而优先级队列是按优先级出队的,优先级高的先出

PriorityBlockingQueue没有大小限制,是无界的,内部的数组大小会动态扩展,要求元素要么实现Comparable接口,要么创建PriorityBlockingQueue时提供一个Comparator对象。

 

延时阻塞队列

延时阻塞队列DelayQueue是一种特殊的优先级队列,它是无界的。

它要求每个元素都实现Delayed接口,该接口的声明为:

1
2
3
public interface Delayed extends Comparable<Delayed> {
    long getDelay(TimeUnit unit);
}

Delayed扩展了Comparable接口,也就是说,DelayQueue的每个元素都是可比较的,它有一个额外方法getDelay返回一个给定时间单位unit的整数,表示再延迟多长时间,如果小于等于0,则表示不再延迟。

DelayQueue可以用于实现定时任务,它按元素的延时时间出队。它的特殊之处在于,只有当元素的延时过期之后才能被从队列中拿走,也就是说,take方法总是返回第一个过期的元素,如果没有,则阻塞等待。

 

其他阻塞队列

SynchronousQueue与一般的队列不同,它不算一种真正的队列,没有存储元素的空间,连存储一个元素的空间都没有。它的入队操作要等待另一个线程的出队操作,反之亦然。如果没有其他线程在等待从队列中接收元素,put操作就会等待。take操作需要等待其他线程往队列中放元素,如果没有,也会等待。SynchronousQueue适用于两个线程之间直接传递信息、事件或任务。

LinkedTransferQueue实现了TransferQueue接口,TransferQueue是BlockingQueue的子接口,但增加了一些额外功能,生产者在往队列中放元素时,可以等待消费者接收后再返回,适用于一些消息传递类型的应用中。

 

BlockingDeque

BlockingDeque定义了一个阻塞的双端队列接口,如下所示。

 可以看到,该接口在继承了BlockingQueue接口的同时,增加了对应的双端队列操作接口。该接口只有一个实现,就是LinkedBlockingDeque。

和LinkedBlockingQueue基本一样,只是Linked BlockingQueue是单向链表,而LinkedBlockingDeque是双向链表。

所谓双向队列指的是可以从队列的两端插入和移出元素。双向队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。相比其他的阻塞队列,LinkedBlockingDeque多了addFirst、addLast、offerFirst、offerLast、peekFirst和peekLast等方法,以First单词结尾的方法,表示插入、获取(peek)或移除双端队列的第一个元素。以Last单词结尾的方法,表示插入、获取或移除双端队列的最后一个元素。另外,插入方法add等同于addLast,移除方法remove等效于removeFirst。但是take方法却等同于takeFirst,使用时还是用带有First和Last后缀的方法更清楚。

 

参考: Java编程的逻辑 17.4 并发队列

  Java并发编程的艺术 6.3.2 Java里的阻塞队列

  Java并发实现原理:JDK源码剖析 5.1 BlockingQueue

 

posted @   草木物语  阅读(91)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2019-01-27 ajax 跨域 springboot
2018-01-27 js,jquery 获取滚动条高度和位置, 元素距顶部距离
2018-01-27 java 向上转型与向下转型
2018-01-27 Java 判断相等
点击右上角即可分享
微信分享提示