赞
踩
Java中的BlockingQueue
接口是一个线程安全的存取队列,适用于生产者消费者的应用场景中,支持两个附加操作:
BlockingQueue
提供四种不同的处理方法。
抛出异常 | 返回特殊值 | 一直阻塞 | 超时退出 | |
---|---|---|---|---|
插入方法 | add(o) | offer(o) | put(o) | offer(o, timeout, timeunit) |
移除方法 | remove(o) | poll() | take(o) | poll(o, timeout, timeunit) |
检查方法 | element() | peek() | — | — |
IllegalStateException
,否则插入成功返回true
。当使用有界(capacity-restricted queue)阻塞队列时,建议使用offer
方法。
IllegalStateException
- if the element cannot be added at this time due to capacity restrictionsClassCastException
- if the class of the specified element prevents it from being added to this queueNullPointerException
- if the specified element is nullIllegalArgumentException
- if some property of the specified element prevents it from being added to this queuetrue
,否则返回false
。如果包含一个或者多个object,那么只移除一个就返回true
。注意:remove(o)
是BlockingQueue
接口的方法,remove()
是Queue
接口的方法。NoSuchElementException
。如果队列不为空,查询返回队列头部的数据,但是不移除数据,这点不同于remove()
,element
同样是Queue
接口的方法。true
,否则返回false
。当使用有界(capacity-restricted queue)阻塞队列时,建议使用offer
方法,不建议会抛出异常的add
方法。Queue
接口的。如果队列不为空,查询、移除并返回队列头部元素。如果队列为空,那么返回null
。Queue
接口的。如果队列为空,返回null
,这点不同于poll
。如果队列不为空,查询返回队列头部的数据,但是不移除数据,这点不同于remove()
。InterruptedException
。InterruptedException
。InterruptedException
。如果插入成功,那么返回true
,如果在达到指定时间后仍然队列不可用,那么返回false
。InterruptedException
。如果删除成功,那么返回队列头部元素,如果在达到指定时间后仍然队列不可用,那么返回null
。Queue
队列不能插入null,否则会抛出NullPointerException
。
JDK7提供了7个阻塞队列。分别是
PriorityQueue
实现的支持延时获取元素的阻塞队列。ArrayBlockingQueue
是基于数组(array-based)的先进先出(FIFO)有界(bounded)阻塞队列。
Collection
来初始化队列元素。notEmpty
、notFull
)算法。LinkedBlockingQueue
是基于链表(linked nodes)的先进先出(FIFO)的可选界(optionally-bounded)的阻塞队列。
Integer.MAX_VALUE
。Collection
来初始化队列元素,此时不能指定队列容量,默认为Integer.MAX_VALUE
。count
即当前队列元素个数,采用AtomicInteger
,避免put
和take
的竞争。ArrayBlockingQueue
不同的是,LinkedBlockingQueue
队列中有两把锁,读锁和写锁是分离的。LinkedBlockingQueue
时,若队列大小为默认值,且生产速度大于消费速度时,可能会内存溢出。LinkedBlockingQueue
理论上来说比ArrayBlockingQueue
有更高的吞吐量,但是在大多数的实际应用场景中,却没有很好的表现。PriorityBlockingQueue
是基于数组(array based)的支持优先级的无界(unbounded)的阻塞队列。此队列的数据结构是堆。
DEFAULT_INITIAL_CAPACITY
为11。PriorityBlockingQueue
的无界(unbounded)相对于LinkedBlockingQueue
的可选界(optionally-bounded)来说,无界是指不能在创建队列时,不能指定队列的最大容量(capacity),并不是说PriorityBlockingQueue
本身无界。LinkedBlockingQueue
默认(注意,这里指的是默认容量,即,你可以指定大于Integer.MAX_VALUE
的值)的最大容量是Integer.MAX_VALUE
,而PriorityBlockingQueue
的最大容量是MAX_ARRAY_SIZE=Integer.MAX_VALUE-8
。PriorityBlockingQueue
无界的另一个意思就是生产者线程不会因为队列满了就阻塞,因为队列是无界的,没有容量满了这一说。offer(E e, long timeout, TimeUnit unit)
的后两个参数没有任何作用查看源代码发现,其方法的实现直接是调用了offer(e)
。但是当队列为空时,take
仍然会阻塞。offer(e)
永远不会返回false
,offer(E e, long timeout, TimeUnit unit)
永远不会返回false
或者阻塞。PriorityBlockingQueue
通过数组来实现队列,在原有数组满了的情况下,通过复制数组来扩展队列容量,如果新扩展的数组容量大小超过MAX_ARRAY_SIZE
,那么抛出OutOfMemoryError
异常。DelayQueue
是基于PriorityQueue
实现的支持延时获取元素的阻塞队列。
DelayQueue
中存放的对象必须实现Delayed
接口。head
,poll
方法返回null。getDelay(TimeUnit.NANOSECONDS)
返回值小于等于0时,该元素过期。take
和poll
移除未过期的元素,但是这些未过期的元素仍然和过期元素一样同等对待。例如,size
方法返回的数量就是过期元素和未过期元素的之和。DelayQueue
的适用场景:
通过上面几条场景例子,可以看出来,DelayQueue
适用于在一定时间后,做某些业务处理。
SynchronousQueue
是一个没有数据缓冲的BlockingQueue
。
SynchronousQueue
适合传递性设计(handoff designs),即一个线程中运行的对象,需要将某些信息、任务或者事件等传递给另一个线程中运行的对象的场景。SynchronousQueue
支持公平和非公平模式。peek
,因为仅在试图要移除元素时,该元素才存在。Executors.newCachedThreadPool()
中就使用了SynchronousQueue
队列。LinkedTransferQueue
是基于链表(linked nodes)的无界(unbounded)阻塞队列。
Integer.MAX_VALUE
),进出队列采用FIFO(先进先出)原则。SynchronousQueue
很类似,但是比起SynchronousQueue
更好用。LinkedTransferQueue
既可以使用BlockingQueue
的put
方法进行常规的添加元素操作,也可以使用transfer
方法进行阻塞添加。SynchronousQueue
灵活之处在于,队列长度非0,阻塞插入和非阻塞插入的元素可以共存。take()
方法或带时间限制的poll()
方法时),transfer
方法可以把生产者传入的元素立刻transfer(传输)给消费者。如果没有消费者在等待接收元素,transfer
方法会将元素存放在队列的tail
节点,并等到该元素被消费者消费了才返回。LinkedBlockingDueue
是基于链表(linked nodes)的可选界(optionally-bounded)的双向阻塞队列。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。