在Java类库中出现的第一个关联的集合类是 Hashtable
。 Hashtable
提供了一种易于使用的、线程安全的、关联的map功能。然而,线程安全性付出代价是――Hashtable
的所有方法都是同步的。Hashtable
的后继者HashMap
是作为JDK1.2中的集合框架的一部分出现的,它通过提供一个不同步的基类和一个同步的包装器Collections.synchronizedMap
,解决了线程安全性问题。通过将基本的功能从线程安全性中分离开来,Collections.synchronizedMap
允许需要同步的用户可以拥有同步,而不需要同步的用户则不必为同步付出代价。
同步的集合包装器 synchronizedMap
和 synchronizedList
,有时也被称作 有条件地线程安全――所有单个的操作都是线程安全的,但是多个操作组成的操作序列却可能导致数据争用,因为在操作序列中控制流取决于前面操作的结果。例如对于这样的功能put-if-absent语句块――如果一个条目不在Map
中,那么添加这个条目。该功能通过containsKey()
方法和 put()
方法组合起来。要保证原子性操作,就需要对该语句块加上同步锁。
Queue接口
java.util 包为集合提供了一个新的基本接口:java.util.Queue,是一个先入先出(FIFO)的数据结构。
PriorityQueue类
BlockingQueue接口
阻塞队列,它实质上就是一种带有一点扭曲的 FIFO 数据结构。它提供了可阻塞的put和take方法。如果Queue已经满了,put方法会被阻塞直到有空间可用;如果Queue是空的,那么take方法会被阻塞,直到有元素可用。Queue的长度可用有限,也可以无限;无限的Queue永远不会充满,所以它的put方法永远不会被阻塞。阻塞队列支持生产者-消费者设计模式。BlockingQueue可以使用任意数量的生产者和消费者,从而简化了生产者-消费者设计的实现。
BlockingQueue接口的几个主要的实现类:
ArrayBlockingQueue
:一个由数组支持的有界队列。LinkedBlockingQueue
:一个由链接节点支持的可选有界队列。PriorityBlockingQueue
:一个由优先级堆支持的无界优先级队列。DelayQueue
:一个由优先级堆支持的、基于时间的调度队列。SynchronousQueue
:一个利用BlockingQueue
接口的简单聚集(rendezvous)机制。PriorityBlockingQueue
是具有无界限容量的队列,它利用所包含元素的Comparable
排序顺序来以逻辑顺序维护元素。可以将它看作TreeSet
的可能替代物。对于没有天然顺序的元素,可以为构造函数提供一个Comparator
。不过对PriorityBlockingQueue,有一个要特别注意的地方:
从iterator()
返回的Iterator
实例,元素是不具有优先级顺序的。如果必须以优先级顺序遍历所有元素,那么让它们都通过toArray()
方法并自己对它们排序,像Arrays.sort(pq.toArray())
。SynChronousQueue,它根本上不是一个真正的队列,因为它不会为队列元素维护任何存储空间。不过,它维护一个排队的线程清单,这些线程等待把元素加入队列或移出队列。它非常直接的移交工作,减少了生产者和消费者之间移动数据的延迟时间。直接移交同样会给生产者带来更多关于任务状态的反馈信息:当移交被接受,它就知道消费者已经得到了任务。 因为SynchronousQueue没有存储的能力,所以除非另一个线程已经准备好参与移交工作,否则put和take会一直阻塞。比较适合于消费者充足的情况。
CopyOnWriteArrayList 和
CopyOnWriteArraySet
,最适合于读操作通常大大超过写操作的情况。