blockingqueue学习总结

来源:互联网 发布:养比特犬体验知乎 编辑:程序博客网 时间:2024/05/29 11:03

定义:

blockingqueue(阻塞队列)支持两种操作,当队列为空时,获取元素的线程会等待队列变为非空,当队列已满时,存储元素的线程会等待队列有空闲可用。阻塞队列通常用于消费者/生产者的场景,生产者就是往队列中添加元素的线程,消费者就是从队列中获取元素的线程,blockingqueue就是生产者存放元素的容器,也是消费者获取元素的容器。


七个实现类:

ArrayBlockingQueue:

一个由数组结构组成的有界阻塞队列。

此队列按照先进先出(FIFO)的原则对元素进行排序,默认情况下不保证访问者公平的访问队列,即当队列可用时,按照阻塞的先后顺序访问队列,先阻塞的生产者线程,可以先往队列里插入元素,先阻塞的消费者线程,可以先从队列中获取元素,通常情况下为了保证公平性会降低吞吐量。

DelayQueue:

一个使用优先级队列(PriorityQueue)实现的无界阻塞队列。

支持延时获取,队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延时期满时才能从队列中提取元素。

应用场景:

缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从队列中获取元素时候,表示缓存有效期到了。

定时任务调度:使用DelayQueue保存当天将会执行的任务和执行时间。一旦从队列中获取到任务就开始执行,比如TimerQueue就是用DelayQueue实现的。

队列中的Delayed必须实现compareTo来指定元素的顺序。

LinkedBlockingDeque:

一个由链表结构组成的双向阻塞队列。

可以从队列的两端插入和获取元素,双端队列因为多了一个操作队列的入口,在多线程同时入队时,减少了一半的竞争。相比其他的阻塞队列,LinkedBlockingDeque多了addFirst,addLast,offerFirst,offerLast,peekFirst,peekLast等方法,以First结尾的方法表示插入/获取(peek)/移除双端队列的第一个元素。以Last结尾的方法,表示插入/获取(peek)/移除双端队列的最后一个元素。add方法等同于addLast方法,remove方法等同于removeFirst方法。

在初始化时可以设置容量防止其过渡膨胀。

LinkedBlockingQueue:

一个由链表结构组成的有界阻塞队列。

此队列按照先进先出(FIFO)的原则对元素进行排序,默认和最大长度为Integer.MAX_VALUE。

LinkedTransferQueue:

一个由链表结构组成的无界阻塞队列

相对于其他阻塞队列,LinkedTransferQueue多了tryTransfer和transfer方法。

transfer方法。如果当前又消费者正在等待接受元素(消费者使用take()或poll(timeout)时),transfer方法可以把生产者传入的元素立刻transfer给消费者。如果没有消费者在等待接收元素,transfer方法会将元素存放在队列的tail节点,并等到该元素被消费了才返回。

tryTransfer方法。则是用来试探下生产者传入的元素是否能直接传给消费者。如果没有消费者等待接收元素,则返回false。和transfer方法的区别是,tryTransfer方法无论消费者是否接收,方法立即返回,而transfer方法是必须等到消费者消费了才返回。

tryTransfer(E e, Long timeout, TimeUnit unit)方法,则是试图把生产者传入的元素直接传给消费者,如果没有消费者消费该元素,则等待指定时间后返回,被消费,返回true,没被消费,返回false。

PriorityBlockingQueue:

一个支持优先级排序无界阻塞队列。

默认情况下元素采取自然顺序排序,也可以通过比较器comparator来指定元素的排序规则,元素按照升序排序。

SynchronousQueue:

一个不存储元素的阻塞队列。

每一个put操作必须等待一个take操作,否则不能继续添加元素,适用于传递性场景,比如在一个线程中使用的数据,传递给另一个线程,SyncchronousQueue吞吐量高于LinkedBlockingQueue和ArrayBlockingQueue。


四种等待形式:

1.抛异常(Throws Exception):IllegalStateException("Queue full")/NoSuchElementException

2.返回一个特殊值(Special value):null/false

3.无限期的锁住当前线程,等待,直到塞入/取出成功(Blocks)

4.超时退出(Times out):设定等待时间

参考如下表格

 Throws ExceptionSpecial valueBlocksTimes outInsertadd(e)offer(e)put(e)offer(e, time, unit)Removeremove()poll()take()poll(time, unit)Examineelement()peek()not applicablenot applicable


方法概述:

addboolean add(E e)

当队列没满时,插入队列成功,返回true,当队列已满,插入队列失败,抛出IllegalStateException异常。
当使用有界队列时,更倾向于使用offer。

Parameters:

e-插入队列对象

Returns:
true

Throws:
IllegalStateException-当要插入的队列已满时
ClassCastException-插入队列的对象类型与队列泛型转换异常
NullPointerException-插入队列的对象为空
IllegalArgumentException-插入非法对象
 offerboolean offer(E e)
当队列没满时,插入队列成功,返回true,当队列已满,返回false。
当使用有界队列时,如果希望队列已满时抛出异常,更倾向于使用add。

Parameters:
e-插入队列对象

Returns:
true/false

Throws:
ClassCastException-插入队列的对象类型与队列泛型转换异常
NullPointerException-插入队列的对象为空
IllegalArgumentException-插入非法对象
 putvoid put(E e)  throws InterruptedException
当队列已满时,等待,直到队列有空闲。

Parameters:
e-插入队列对象

Throws:
InterruptedException-阻塞过程中发生异常
ClassCastException-插入队列的对象类型与队列泛型转换异常
NullPointerException-插入队列的对象为空
IllegalArgumentException-插入非法对象
 offerboolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException
当队列已满时,在指定时间内等待,直到队列有空闲。

Parameters:
e-插入队列对象
timeout-超时时间
unit-时间单位

Returns:
true/false

Throws:
InterruptedException-阻塞过程中发生异常
ClassCastException-插入队列的对象类型与队列泛型转换异常
NullPointerException-插入队列的对象为空
IllegalArgumentException-插入非法对象
 takeE take() throws InterruptedException
获取并移除队列头部的对象,等待,直到队列中有对象可用。

Returns:
队列顶部的对象

Throws:
InterruptedException-阻塞过程中发生异常
 pollE poll(long timeout, TimeUnit unit) throws InterruptedException
获取并移除队列头部的对象,在指定时间内等待,直到队列中有对象可用。

Parameter:
timeout-超时时间
unit-时间单位

Returns:
队列顶部的对象/null(超时)

Throws:
InterruptedException-阻塞过程中发生异常
 remainingCapacityint remainingCapacity()
返回在队列不阻塞的情况下,剩余可添加对象数,如果是无界队列,或者没有设置队列限制,则返回Integer.MAX_VALUE
注意,我们无法根据队列现有的剩余容量情况,确保一个线程能插入成功,因为其他线程也有可能插入或移除对象。

Returns:
剩余容量
 removeboolean remove(Object o)
移除队列中的单个实例,如果该实例存在。通常的,如果队列中存在一个或多个入参中的元素,移除队列中与这个元素相等的元素。如果队列中存在这个元素,则返回true。

Parameter:
o-需要被从队列中移除的对象

Throws:
ClassCastException-插入队列的对象类型与队列泛型转换异常
NullPointerException-插入队列的对象为空
 containsboolean contains(Object o)
如果参数中元素存在于队列中,则返回true。通常的,如果队列中存在一个或多个入参中的元素,则返回true。

Parameter:
o-需要校验是否存在于队列中的对象

Throws:
ClassCastException-插入队列的对象类型与队列泛型转换异常
NullPointerException-插入队列的对象为空
 drainToint drainTo(Collecntion<? super E> c)
从队列中移除所有元素,添加到入参指定的集合中,此操作要比多次从队列中poll操作更高效。当试图向入参指定的集合中添加元素时,会发生失败情况。当关联异常被抛出,表示两个集合和队列可能两者都不会添加,可能添加到其中一个,也可能两者都被添加入该元素。

Parameter:
c-元素要传输的集合

Return:
传输成功的元素个数

Throws:
UnsupportedOperationException-集合不支持添加的元素
ClassCastException-插入队列的对象类型与队列泛型转换异常
NullPointerException-插入队列的对象为空
IllegalArgumentException-插入非法对象
 drainToboolean drainTo(Collection<? extends E> c, int maxElements)
从队列中移除所有元素,添加到入参指定的集合中,此操作要比多次从队列中poll操作更高效。当试图向入参指定的集合中添加元素时,会发生失败情况。当关联异常被抛出,表示两个集合和队列可能两者都不会添加,可能添加到其中一个,也可能两者都被添加入该元素。如果企图将队列转换入自己本身,将抛IllegalArgumentException异常。更进一步的,如果指定集合在操作过程中被改动了,未定义该操作的行为。

Parameters:
c-元素要转换添加的集合
maxElements-传输元素的最大个数

Returns:

被传输的元素个数

Throws:

UnsupportedOperationException-集合不支持添加的元素

ClassCastException-插入队列的对象类型与队列泛型转换异常

NullPointerException-插入队列的对象为空

IllegalArgumentException-插入非法对象


参考资料:

1.https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html

2.http://www.infoq.com/cn/articles/java-blocking-queue


demo文档

原创粉丝点击