LinkedBlockingDeque
LinkedBlockingDeque: 由双向链表组成的有界阻塞队列,队列容量大小可选,默认大小为Integer.MAX_VALUE。队头部和队尾都可以写入和移除元素,因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半锁的竞争 。
LinkedBlockingDeque是双向链表实现的阻塞队列。该阻塞队列同时支持FIFO和FILO两种操作方式,即可以从队列的头和尾同时操作(插入/删除);
在不能够插入元素时,它将阻塞住试图插入元素的线程;在不能够抽取元素时,它将阻塞住试图抽取的线程。;
LinkedBlockingDeque还是可选容量的,防止过度膨胀,默认等于Integer.MAX_VALUE。;
LinkedBlockingDuque没有进行读写锁的分离,因此同一时间只能有一个线程对其操作,因此在高并发应用中,它的性能要远远低于LinkedBlockingQueue。
Deque特性: 队头和队尾都可以插入和移除元素,支持FIFO和FILO。
相比于其他阻塞队列,LinkedBlockingDeque多了addFirst()、addLast()、peekFirst()、peekLast()等方法,以XXXFirst结尾的方法,表示插入、获取获移除双端队列的队头元素。以xxxLast结尾的方法,表示插入、获取获移除双端队列的队尾元素。
假设:有多个消费者,每个消费者有自己的一个消息队列,生产者不断的生产数据扔到队列中,消费者消费数据有快有慢。为了提升效率,速度快的消费者可以从其它消费者队列的队尾出队元素放到自己的消息队列中,由于是从其它队列的队尾出队,这样可以减少并发冲突(其它消费者从队首出队元素),又能提升整个系统的吞吐量。这其实是一种“工作窃取算法”的思路。
BlockingDeque相对于BlockingQueue,最大的特点就是增加了在队首入队/队尾出队的阻塞方法。下面是两个接口的比较:
可以看first指向队首节点,last指向队尾节点。利用ReentrantLock来保证线程安全,所有对队列的修改操作都需要先获取全局锁
初始:
队首插入节点node:
初始:
队尾插入节点node:
可响应中断阻塞式队首入队-void putFirst(E e)
可响应中断阻塞式队尾入队-void putLast(E e)
非阻塞式队首入队-boolean offerFirst(E e)
非阻塞式队尾入队-boolean offerLast(E e)
可响应中断限时阻塞队首入队-boolean offerFirst(E e, long timeout, TimeUnit unit)
可响应中断限时阻塞队尾入队-boolean offerLast(E e, long timeout, TimeUnit unit)
非阻塞队首入队(抛异常)-void addFirst(E e)
非阻塞队尾入队(抛异常)-void addLast(E e)
非阻塞式队尾入队-boolean add(E e)
可响应中断阻塞式队尾入队-void put(E e)
非阻塞式队尾入队-boolean offer(E e)
可响应中断限时阻塞队尾入队-boolean offer(E,long,TimeUnit)
初始:
删除队首节点:
从队尾出队last节点,一定会将prev指针指向自身,以区别于非出队时last指向具体节点(即prev指针不会指向自身,可能为真实节点或null)。
初始:
删除队尾节点:
出队核心方法-void unlink(Node x)
可响应中断阻塞式队首出队-E takeFirst()
可响应中断阻塞式队尾出队-E takeLast()
非阻塞式队首出队-E pollFirst()
非阻塞式队尾出队-E pollLast()
可响应中断限时阻塞队首出队- E pollFirst(long timeout, TimeUnit unit)
可响应中断限时阻塞队尾出队- E pollLast(long timeout, TimeUnit unit)
不移除元素队首出队-E peekFirst()
不移除元素队尾出队-E peekLast()
非阻塞队首出队(抛异常)-E removeFirst()
非阻塞队尾出队(抛异常)–E removeLast()
从队首向后移除指定元素-boolean removeFirstOccurrence(Object o)
从队尾向前移除指定元素-boolean removeLastOccurrence(Object o)
可响应中断阻塞式队首出队-E take()
非阻塞式出队-E poll()
阻塞式超时出队-E poll(timeout, unit)
阻塞式出队-E peek()
移除元素- E remove()
此迭代器是弱一致性的。因为即使节点被删除, 迭代器也会照样返回被删除节点的item 。
正向迭代器和反向迭代器 只需要实现2个抽象方法。
LinkedBlockingDeque是一个 无界阻塞双端队列 ,相比普通队列,主要是多了【队尾出队元素】/【队首入队元素】的功能。