一、Vector和HashTable
Vector和ArrayList类似,都是长度可变的数组,不同的是,Vector是线程安全的,它给几乎所有的public方法加上了synchronized关键字。由于加锁导致性能下降,在不需要并发访问某一对象时,强制性的同步机制会显得多余,Vector目前已被弃用。
同样地,HashTable和HashMap类似,但HashTable是线程安全的,它也是给几乎所有的public方法加上了synchronized关键字。HashTable和HashMap的另一个不同点是HashTable的K和V不允许为空。目前由于的性能原因,HashTable已被弃用。
二、Collections包装的方法
ArrayList和HashMap替代了Vector和HashTable,但由于它们是线程不安全性,所以Collections提供了相应的包装的方法将它们包装成线程安全类,如下所示:
List<E> synArrayList = Collections.synchronizedList(new ArrayList<E>());
Set<E> synHashSet = Collections.synchronizedSet(new HashSet<E>());
Map<K, V> synHashMap = Collections.synchronizedMap(new HashMap<E>());
...
Collections为每种集合都声明了线程安全的包装类,在原集合的基础上添加了锁对象,集合中的方法通过锁对象实现同步。
三、java.util.concurrent包中的集合
1、ConcurrentHashMap
ConcurrentHashMap和HashTable都是线程安全类,不同之处在于加锁粒度上。HashTable的加锁方法是给每个方法加上synchronized关键字,锁住的是这个Table对象,而ConcurrentHashMap是更加细粒度的加锁。
JDK1.8之前,ConcurrentHashMap是对Segment片段加锁,是Table的一部分,不同Segment之间的并发操作不会相互影响。JDK1.8之后,取消了Segment字段,ConcurrentHashMap直接在Table的元素上进行加锁,进一步减少了并发冲突的概率。
2、CopyOnWriteArrayList和CopyOnWriteArraySet
CopyOnWriteArrayList和CopyOnWriteArraySet是加了写锁的ArrayList和ArraySet,锁住的是整个对象,但读操作可以并发执行。
3、其他
ConcurrentSkipListMap、ConcurrentSkipListSet、ConcurrentLinkedQueue、ConcurrentLinkedDeque等都是线程安全的集合,但是其中并没有ConcurrentArrayList,因为不能开发出一个通用且可以规避ArrayList开发瓶颈的线程安全类,只能锁住整个List,这用Collections的包装类就可以办到。