[Java 多线程] 并发集合类

来源:互联网 发布:网络口语 编辑:程序博客网 时间:2024/05/29 13:46

ConcurrentHashMap
JDK 1.5 中的java.util.concurrent 包是对Map 的线程安全的实现,比起synchronizedMap 来,他提供的并发性要好的多。可以同时的(并发的)执行读写操作。
ConcurrentHashMap 被设计用来优化检索操作,实际上,成功的get() 操作完成后,通常根本不会有锁着的资源。
ConcurrentHashMap 通过稍微的松弛他对调用者的承诺而获得了更高的并发性。检索操作将可以返回由最近完成的插入操作所插入的值,也可以返回在步调上是并发的插入操作所添加的值。由ConcurrentHashMap.iterator() 返回的Iterators 将每次最多返回一个元素,并且不会抛出ConcurrentmodificationException 异常,但是可能会也可能不会反映在该迭代器被构建之后发生的插入操作或者移除操作。在对集合迭代时,不需要集合范围的锁就能提供线程安全。
在任何不依赖锁整个表来防止更新的应用程序中,可以使用ConcurrentHashMap 来代替synchronizedMap 或 Hashtable。

CopyOnWriteArrayList
在那些遍历操作大大地多于插入或移除操作的并发应用程序中,一般用CopyOnWriteArrayList 类代替ArrayList。
如果你正在使用一个普通的ArrayList 来存放一个监听器列表,那么只要该列表示可变的,且可能被多线程访问,你就必须要么在对其迭代操作期间,要么在迭代前进行的克隆操作期间,锁定整个列表,这两种方法的开销多很大。当对列表执行会引起列表发生变化的操作时,CopyOnWriteArrayList 并不是为列表创建一个全新的副本,它的迭代器肯定能够返回在迭代器被创建时列表的状态,而不会抛出 ConcurrentModificationException 。在对列表进行迭代之前不必克隆列表或者在迭代期间锁定列表,因为迭代器所看到的列表的副本是不变的。换句话说, CopyOnWriteArrayList 含有对一个不可变数组的一个可变的引用,因此,只要保留好那个引用,您就可以获得不可变的线程安全性的好处,而且不用锁定列表。

 

总结:

同步的集合类 Hashtable 和 Vector ,以及同步的包装器类 Collections.synchronizedMap 和 Collections.synchronizedList ,为 Map 和 List 提供了基本的有条件的线程安全的实现。然而,某些因素使得它们并不适用于具有高度并发性的应用程序中――它们的集合范围的单锁特性对于可伸缩性来说是一个障碍,而且,很多时候还必须在一段较长的时间内锁定一个集合,以防止出现ConcurrentModificationExceptions异常。 ConcurrentHashMap 和 CopyOnWriteArrayList 实现提供了更高的并发性,同时还保住了线程安全性,只不过在对其调用者的承诺上打了点折扣。 ConcurrentHashMap 和 CopyOnWriteArrayList 并不是在您使用HashMap 或 ArrayList 的任何地方都一定有用,但是它们是设计用来优化某些特定的公用解决方案的。许多并发应用程序将从对它们的使用中获得好处。

 

本文摘自: Java 理论与实践: 并发集合类