5.2并发容器    
    Java5.0通过提供几种并发的容器类来改进同步容器。同步容器通过对容器的所有状态进行串行访问,从而实现了它们的线程安全。这样做的代价是削弱了并发性,当多个
线程共同竞争容器级的锁时,吞吐量会降低。
    另一方面,并发容器是为多线程并发访问而设计的。
    因为ConcurrentHashMap不能够在独占访问中被加锁,我们不能使用客户端加锁来创建新的原子操作。
5.3阻塞队列和生产者-消费者模式
    阻塞队列支持生产者-消费者设计模式。一个生产者-消费者设计分离了“识别需要完成的工作”和“执行工作”。
    阻塞队列的take会保存阻塞直到可用数据出现和put方法的阻塞特性大大简化了编码。如果我们使用一个有界队列,那么当队列充满的时候,生产者就会阻塞,暂不能生成
更多的工作,从而给消费者时间来追赶进度。
    阻塞队列同样提供了一个offer方法,如果条目不能被加入到队列里,它会返回一个失败状态。这使得你能创建更多灵活的策略来处理超负荷工作,比如减轻负载,序列化剩余
工作条目并写入硬盘,减少生产者线程,或者用其他的方法遏制生产者线程。
    有界队列是强大的资源管理工具,用来建立可靠的应用程序:它们遏制那些可以产生过多工作量、具有威胁的活动,从而让你的程序在面对超负荷工作时更加健壮。
    在你的设计初期就使用阻塞队列建立对资源的管理---提早做这件事情会比日后再修复容易的多。
    在某些情况下,阻塞队列使这更加简单,但是如果阻塞队列并不完全适合于你的设计,你也可以用信号量创建其他的阻塞数据结构。
5.3.2连续的线程限制
    在java.util.concurrent中实现的阻塞队列,全部都包含充分的内部同步,从而能安全地将对象从生产者线程发布至消费者线程。
5.3.3双端队列和窃取工作
    双段队列允许高效地在头和尾分别进行插入和移除。
    正如阻塞队列适用于生产者-消费者模式一样,双端队列使它们自身与一种叫做窃取工作的模式相关联。
    在窃取工作的设计中,每一个消费者都有一个自己的双端队列。如果一个消费者完成了自己双端队列中的全部工作,它可以偷取其它消费者的双端队列中的末尾任务。
5.4阻塞和可中断的方法
    一个阻塞的操作和一个普通的操作之间的差别仅仅在于,被阻塞的线程必须等待一个时间的发生才能继续进行,并且这个事件是超越它自己控制的,因而需要花费更长的时间
--等待I/O操作完成,锁可用,或者是外部计算结束。
5.5Synchronizer
    所有的Synchronizer都享有类似的结构特性:它们封装状态,而这些状态决定着线程执行到在某一点时是通过还是被迫等待的;它们还提供操控状态的方法,以及高效地
等待Synchronizer进入到期望状态的方法。
5.5.1 闭锁
    闭锁可以用来确保特定活动直到其他的活动完成后才发生。
5.5.2 FutureTask
    FutureTask同样可以作为闭锁。FutureTask的实现描述了一个抽象的可携带结果的计算。FutureTask的计算是通过Callable实现的,它等价于一个可携带结果的Runnable。
并且有3个状态:等待、运行和完成。完成包括所有计算以任意的方式结束,包括正常结束、取消和异常。一旦FutureTask进入完成状态,它会永远停止在这个状态上。