Java进阶7并发优化4——JDK并发数据结构20131114
由于并发程序和串行程序的不同特点,在串行程序中使用的数据结构可能无法在并行程序中直接的正常使用,因为这些数据结构可能不是线程安全的,所以这一次并发程序的优化介绍的是并发程序中的数据结构,比如并发List,并发Set,并发Map等。
1.并发List
Vector实现的List接口,CopyOnWriteArrayList也是实现的List接口,这两个List的实现是线程安全的,但是对于ArrayList不是线程安全的,所以在多线程中尽量避免使用ArrayList,如果因为某些原因必须使用的话,需呀使用同步机制:
Collection.synchronizedList(List list)对List进行封装,封装成为线程安全的List。
CopyOnWriteArrayList:实现的机制与Vector的机制是不同的,当对对象进行写操作的时候,复制该对象;如果是进行读操作的话,那么就直接返回结果,不需要同步;核心思想就是减少所得竞争,从而提高程序的性能,但是这个数据结构在一定程度上牺牲了写的性能。
Vector的实现使用的是同步机制,get所有的操作必须是首先获得对象的锁才可以进行,在高并发的情况支架,锁机制会拖累系统性能。
Vector适合写操作,CopyOnWriteArrrayList适合的是读操作并发程序
2.并发Set
类似List,Set 也有一个CopyOnWriteArraySet,而且是线程安全的,内部实现完全依赖于CopyOnWriteArrayList,适合使用在读操作多的并发场景,当然也可以使用的是
Collections中的静态方法将数据结构转换成为线程安全的。
public static <T> Set<T> synchronizedSet(Set<T> s);
3.并发Map
同样可以使用Collectionsz中的synchornizedMap()方法转换,但是性能比较差,JDK中提供了一个比较高效的Map数据结构:ConcurrrentHashMap.他的get是无锁的,他的put的锁粒度是比较小的,所以效率会比较高。
4.并发Queue
JDK中有两种代表性的实现:ConcurrentLinkedQueue为代表的高性能队列和BlockingQueue为接口的阻塞队列,都是集成Queue接口。
ConcurrentLinkedQueue适合的是高并发场景的队列,通过无锁的方式实现的,而且性能是高于BlockingQueue。
5.并发Deque
在JDK中实现了双端队列,可以在头部和尾部实现出队和入队,他有三个实现类:LinkedList,ArrayDeque, LinkedBlockingDeque。它们都实现了双端队列的接口 Deque。ArrayDeque是基于Array实现的,拥有高效的随机访问性质,但是当队列变大的时候,就需要重新分配内存空间,并且才需要复制数值;所以LinkedList会表现出更好的性能。以上两者都不是线程安全的。
需要使用LinkedBlockingDeque,这是一个线程安全的Deque的实现,他没有实现读写锁的分离,所以高并发系统中性能是地狱LinkedBlockingQueue的。
Tengfei Yang
In Sun Yat-sen University 2013.11.14