限定阻塞时长。
抛异常 特殊值 阻塞 超时插入 add(e) offer(e) put(e) offer(e, time, unit)
移除 remove() poll() take() poll(time, unit)
检查(获取但不移除队列头部元素) element() peek()
阻塞队列不接受null元素,如果调用add、put、offer尝试添加一个null元素,将会抛出NullPointerException异常,当调用poll操作失败时也会返回null。阻塞队列可能有容量限制,无论何时都不能向队列添加超过剩余容量的元素,否则只能调用put方法陷入阻塞,直到有剩余的空间可以容纳元素。如果对队列的容纳空间没有限制,则剩余容量返回Integer.MAX_VALUE。阻塞队列的实现一般用于生产者-消费者队列的场景,此外阻塞队列还实现了Collection接口,因此,队列还可以使用remove(x)来移除元素。
阻塞队列是线程安全的,所有排队方法的实现都是用内部锁或者其他并发控制手段来实现原子性的。然而,除非是特殊规定,否则大部分集合操作,如:addAll、containsAll、retainAll 、removeAll不一定要保证原子性。因此,可能出现在调用addAll(c)时,只添加c中一部分的元素就抛出异常。阻塞队列本质上并不支持关闭的操作,如:close或shutdown,当有需要让队列不再接受新元素。如果有这种需要或者特性更倾向于以来队列的实现。一种常见的策略是生产者往队列插入具有特殊标识的对象,当消费者使用对象时,会对特殊标识进行解释。
注意,阻塞队列允许多个生产者和消费者同时使用,如下:
class Producer implements Runnable { private final BlockingQueue queue; Producer(BlockingQueue q) { queue = q; } public void run() { try { while (true) { queue.put(produce()); } } catch (InterruptedException ex) { ... handle ...} } Object produce() { ... } } class Consumer implements Runnable { private final BlockingQueue queue; Consumer(BlockingQueue q) { queue = q; } public void run() { try { while (true) { consume(queue.take()); } } catch (InterruptedException ex) { ... handle ...} } void consume(Object x) { ... } } class Setup { void main() { BlockingQueue q = new SomeQueueImplementation(); Producer p = new Producer(q); Consumer c1 = new Consumer(q); Consumer c2 = new Consumer(q); new Thread(p).start(); new Thread(c1).start(); new Thread(c2).start(); } }