Java集合之Queue
来源:互联网 发布:七氟醚mac值换算 编辑:程序博客网 时间:2024/05/18 02:41
Queue
一般我们说的Queue是FIFO,此外还有指定排序方式的PriorityQueue以及LIFO(Stack),以下情况Queue默认都指FIFO.
Queue主要提供的方法就是入队和出队,出队时区分在获取队首元素时是否删除队首元素,此外在入队出队时区分失败时是否抛出异常。
成功时三种类型操作语义相同,如果我们容忍失败,比如队列为空时获取删除、队列大小固定时添加,应该使用offer/poll/peek方法。
Queue内部数组和链表
队列分单向队列和双向队列以及阻塞和非阻塞
单向AbstractQueue
AbstractQueue主要实现了Queue中的add/remove/element方法,本质上还是调用offer/poll/peek, 只是在失败是会抛出异常,而非返回false/null
public boolean add(E e) { if (offer(e)) return true; else throw new IllegalStateException("Queue full");}public E remove() { E x = poll(); if (x != null) return x; else throw new NoSuchElementException();}public E element() { E x = peek(); if (x != null) return x; else throw new NoSuchElementException();}
单向Queue其实是双向Queue的特例,JDK中没有提供单向非阻塞Queue的实现,一般的非阻塞Queue都是双向Queue。
线程安全ConcurrentLinkedQueue
线程安全的基于链表实现的AbstractQueue,采用CAS实现线程安全
阻塞BlockingQueue
队列为空获取元素或队列已满添加元素会阻塞在那里,提供了put(e)/take()阻塞方法,以及带有超时时间的offer/poll方法。
BlockingQueue都是线程安全的。
ArrayBlockingQueue
基于循环数组实现,初始长度在构造函数中给出,队列的长度受限,用以保证生产者与消费者的速度不会相差太远。有一把公共的锁和notFull、notEmpty两个Condition管理队列满或空时的阻塞状态。
LinkedBlockingQueue
可指定初始长度,如不指定则为Integer.MAX_VALUE,利用链表的特征,分离了takeLock与putLock两把锁,用notEmpty、notFull两个condition管理队列满或空时的阻塞状态。
双向Deque
Deque(Double Ended Queue)继承自Queue,Deque的特性是在队尾和队首都可以添加删除获取,因此,除了实现Queue中的方法,它提供了语义更明确的方法,同样区分失败时是否抛出异常。
队首:
队尾:
ArrayDeque
使用循环数组实现,默认数组大小为16,当数组满时动态扩容至两倍。
LinkedList
List中介绍过,LinedList是双向链表,实现了Deque接口。
线程安全ConcurrentLinkedDeque
线程安全的基于链表实现的DeQueue,采用CAS实现线程安全
阻塞BlockingDeque
无ArrayBockingDeque
LinkedBlockingDeque
同LinkedBlockingQueue
PriorityQueue
PriorityQueue是用小顶堆来实现的,堆是二叉完全平衡树,使用数组来保存,Queue(n)的child是Queue(2n+1)和Queue(2n+2), Queue(n) <= Queue(2n+1) && Queue(n) <= Queue(2n+2), Queue(2n+1)与Queue(2n+2)大小关系不定,因此PriorityQueue中Queue(0)是堆顶且最小,出队的总是堆顶,因此优先级越低越先出队,并不是FIFO。如果希望优先级高的先出队就在实现Comprator时比较取负。
入队时放入数组末尾,然后跟parent比较,如果比parent小,就不断向上移动进行调整。
出队时选取Queue(0)后,就需要从左右child中选出最小的元素填充Queue(0), 虽然最小的元素一定是左右child之一,但直接填充会破坏完全二叉树结构,因此将最后一个元素Queue(size)放入Queue(0),然后再堆顶自上向下不断调整。
Queue(n)的左右child之间并无大小关系,因此,通过iterator遍历Queue并不有序。
由于内部是数组,在入队之前会检查队列是否满,如果已满会动态扩容为原来的1.5倍。
我们知道堆可以用来求解TopN问题,既然PriorityQueue内部是堆,也就可以用来求解TopN,只需将PriorityQueue内部大小限定为N,当有第N+1个元素入队时,就将队首元素出队,这样PriorityQueue内部保存的总是Priority最高的N个元素。我们开源的SQL on Storm解决方案Pike支持select top n内部解析就使用的是PriorityQueue实现的。
https://github.com/PPTV/Pike/blob/master/pike/src/main/java/com/pplive/pike/generator/trident/TopNAggregator.java
PriorityBlockingQueue
无界的PriorityQueue,内部结果同PriorityQueue,使用一把公共的锁实现线程安全。因为无界,空间不够时会自动扩容,所以入列时不会锁,出列为空时才会锁。
DelayQueue
public class DelayQueue<E extends Delayed> extends AbstractQueue<E> implements BlockingQueue<E> { private transient final ReentrantLock lock = new ReentrantLock(); private final PriorityQueue<E> q = new PriorityQueue<E>();}public interface Delayed extends Comparable<Delayed> { /** * Returns the remaining delay associated with this object, in the * given time unit. * * @param unit the time unit * @return the remaining delay; zero or negative values indicate * that the delay has already elapsed */ long getDelay(TimeUnit unit);}
DelayQueue = BlockingQueue + PriorityQueue + Delayed,内部是PriorityQueue,
同样是无界的,出列时才会锁。一把公共的锁实现线程安全。元素需实现Delayed接口,每次调用时需返回当前离触发时间还有多久,小于0表示该触发了。pull()时会用peek()查看队头的元素,检查是否到达触发时间。Delay时间最短的在堆顶,当到达Delay时间后,堆顶元素优先出队。
DelayQueue一般用于保存有生命周期的对象,ScheduledThreadPoolExecutor用了类似的结构。
SynchronousQueue
长度为0,不能调用peek()方法来看队列中是否有数据元素,生产者线程对其的插入操作put必须等待消费者的移除操作take,反过来也一样。放入元素时,比如等待元素被另一条线程的消费者取走再返回。多用用线程间传递元素,JDK线程池里用它。
TransferQueue
TransferQueue继承了BlockingQueue并扩展了一些新方法。BlockingQueue(和Queue)是Java 5中加入的接口,它是指这样的一个队列:当生产者向队列添加元素但队列已满时,生产者会被阻塞;当消费者从队列移除元素但队列为空时,消费者会被阻塞。
TransferQueue则更进一步,生产者会一直阻塞直到所添加到队列的元素被某一个消费者所消费(不仅仅是添加到队列里就完事)。新添加的transfer方法用来实现这种约束。顾名思义,阻塞就是发生在元素从一个线程transfer到另一个线程的过程中,它有效地实现了元素在线程之间的传递(以建立Java内存模型中的happens-before关系的方式)。
在队列中已有元素的情况下,调用transfer方法,可以确保队列中被传递元素之前的所有元素都能被处理。
LinkedTransferQueue实现了TransferQueue接口,内部使用CAS保持同步。
- Java集合之Queue
- java集合之Queue
- Java集合之Queue
- JAVA基础知识之Queue集合
- Java基础之(三十二)Queue集合
- Java集合之Stack与Queue介绍
- Java集合之Queue和Deque接口
- Java 集合 之 Queue 和 Stack
- C#集合之Queue
- Collection集合之Queue集合
- Java的Queue集合
- java的Queue集合
- Java集合:队列: Queue
- Java 集合 Queue
- java集合类Queue
- java集合--Queue用法
- java集合--Queue用法
- java集合类深入分析之Queue篇
- cenos7配置阿里云加速
- jsp+servlet+javaBean+mysql (MVC)模拟用户登录
- C++继承内存布局
- 梯度更新方法:Momentum
- join运行机制
- Java集合之Queue
- pom.xml中project.reporting.outputEncoding
- Centos7安装Docker CE版
- Spring体系结构
- ElasticSearch的安装以及插件安装
- 悉尼峰会:公有云与 OpenStack 私有云的价格分析
- 字符串的匹配模式:朴素的模式匹配算法(BF算法)
- linux虚拟网卡驱动
- hashmap冲突的解决方法以及原理分析