定义
阻塞队列是一个支持两个附加操作的队列,即:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。
常用方法
处理方式 | 抛出异常 | 返回特殊值 | 一直阻塞 | 超时退出 |
---|---|---|---|---|
插入方法 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除方法 | remove() | poll() | take() | poll(time,unit) |
检查方法 | element() | peek() | 不可用 | 不可用 |
备注:peek() 返回队列头部的元素,如果队列为空,则返回null;element()如果队列为空,则抛出一个NoSuchElementException异常。
JDK提供的7中阻塞队里
ArrayBlockingQueue
基于数组的有界阻塞队列,创建队列的时候必须制定队列的大小,使用一把锁。
LinkedBlockingQueue
基于链表的有界阻塞队列,创建队列的时候可以不指定队列的大小,默认和最大长度为2^31-1;由于读只操作对头,而写只操作队尾,这里巧妙地采用了两把锁,对于put和offer采用一把锁,对于take和poll则采用另外一把锁,避免了读写时互相竞争锁的情况,因此LinkedBlockingQueue在高并发读写操作都多的情况下,性能会较ArrayBlockingQueue好很多,在遍历以及删除元素则要两把锁都锁住。因为遍历和删除的时候不知道元素的具体位置。
PriorityBlockingQueue
基于堆实现的具有优先级的阻塞队列,默认长度为11,最大长度为2^31-8;队列中的元素必须是可比较的,即实现Comparable接口,或者在构建函数时提供可对队列元素进行比较的Comparator对象。
DelayQueue
DelayQueue是基于PriorityQueue实现的支持延时获取数据的队列。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素
使用场景
-
缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
-
定时任务调度:使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。
SynchronousQueue
一个不存储元素的阻塞队列,非常适合于传递性场景,比如在一个线程中使用的数据,传递给另外一个线程使用,SynchronousQueue的吞吐量高于LinkedBlockingQueue和ArrayBlockingQueue。
LinkedTransferQueue
基于链表的有界阻塞队列,相对于其他阻塞队列LinkedTransferQueue多了tryTransfer和transfer方法。
方法
- transfer(E e)
若当前存在一个正在等待获取的消费者线程,即立刻移交之;否则,会插入当前元素e到队列尾部,并且等待进入阻塞状态,到有消费者线程取走该元素。 - tryTransfer(E e)
若当前存在一个正在等待获取的消费者线程(使用take()或者poll()函数),使用该方法会即刻转移/传输对象元素e;
若不存在,则返回false,并且不进入队列。这是一个不阻塞的操作。 - tryTransfer(E e, long timeout, TimeUnit unit)
若当前存在一个正在等待获取的消费者线程,会立即传输给它; 否则将插入元素e到队列尾部,并且等待被消费者线程获取消费掉,
若在指定的时间内元素e无法被消费者线程获取,则返回false,同时该元素被移除。 - hasWaitingConsumer()
判断是否存在消费者线程 - getWaitingConsumerCount()
获取所有等待获取元素的消费线程数量
LinkedBlockingDeque
是一个由链表结构组成的双向阻塞队列。所谓双向队列指的你可以从队列的两端插入和移出元素。
网友评论