现在你已经知道了Java多线程编程的基础。但是,在实际编程过程中,你希望不要使用这种底层结构,通常,使用设计者设计好的上层结构比使用底层结构更加简单,而且安全。
很多线程问题可以使用一个或多个队列优雅而安全地解决。生产者线程向队列中插入元素,而消费者线程从队列中获取元素,队列可以让对象安全地从一个线程转移到另外一个线程。比如,考虑我们的银行转账程序。我们不直接操作对象,而是向队列中插入转账指令,另外一个线程读取转账指令,然后执行指令。只有这两个线程才有机会访问对象,我们也不需要同步。(当然,这个队列的设计者还是需要考虑线程问题的,但是你不需要)
阻塞队列会在队列满了但是你还在向里面写数据时,阻塞你的线程;在队列空了,但是你还在从里面读数据时,阻塞你的线程。阻塞队列是非常有用的工具,当两个线程分别进行读写操作时,他会自动调节两个线程的速度。它的方法主要包括:

方法

正常状态

特殊条件

add

添加一个元素

如果队列满了,抛出IllegalStateException

element

返回第一个元素

如果队列空,抛出NoSuchElementException

offer

添加一个元素,返回true

如果队列满了,返回false

peek

返回第一个元素

如果队列空,返回null

poll

返回并删除第一个元素

如果队列空,返回null

put

添加一个元素

如果队列满了,则阻塞

remove

返回并删除第一个元素

如果队列为空,抛出NoSuchElementException

take

返回并删除第一个元素

如果队列为空,则阻塞

根据队列为空或满了时,队列的反应,可以将方法分为三类,如果你将它用于线程控制,你应该使用put和take方法。add, remove和element会抛出异常。但是,在多线程条件下,很多情况下,队列都是空的或者满的,所以你应该使用offer, poll和peek方法,他们会使用返回值表示队列状态。
需要注意,poll和peek方法使用null表示操作失败,所以队列中不允许存在null值。
offer和poll可以接受超时参数,比如

boolean success = q.offer(x,100,TimeUnit.MILLISECONDS);

会在100毫秒之内,尝试向队列中写入元素,如果成功,就返回true,否则返回false。类似

Object head =  q.poll(100,TimeUnit.MILLISECONDS);

在100毫秒内尝试从队列中获取元素,如果成功,返回需要的值,否则,返回null表示失败。
java.util.concurrent包提供了其他阻塞队列的变体。默认情况下,LinkedBlockingQueue没有最大的大小限制。LinkedBlockingDeque是双端队列。ArrayBlockingQueue使用给定的大小构建队列,还有一个参数表示公平。当给定公平参数时,等待时间最长的线程会被特殊对待。通常,这种公平机制会使性能得到提升,你应该仅在需要他的时候使用。
PriorityBlockingQueue是优先队列,而不是先入先出队列。队列中的元素按照优先级顺序读取。队列长度不限,但是当队列为空时,线程会被阻塞。
最终,DelayQueue包含实现了Delayed接口的对象

interface Delayed extends Comparable<Delayed>
{
	long getDelay(TimeUnit unit);
}

getDelay方法返回当前的延迟值,负值表示已经超时。只有当数据超时后,数据才能被移除。你还要实现compareTo方法,DelayQueue是用这个方法排序。