并发容器的简单介绍
JDK5中添加了新的concurrent包,相对同步容器而言,并发容器经过一些机制改进了并发性能。由于同步容器将全部对容器状态的访问都串行化了,这样保证了线程的安全性,因此这种方法的代价就是严重下降了并发性,当多个线程竞争容器时,吞吐量严重下降。所以Java5.0开始针对多线程并发访问设计,提供了并发性能较好的并发容器,引入了java.util.concurrent包。与Vector和Hashtable、Collections.synchronizedXxx()同步容器等相比,util.concurrent中引入的并发容器主要解决了两个问题:java
- 1)根据具体场景进行设计,尽可能避免synchronized,提供并发性。
- 2)定义了一些并发安全的复合操做,而且保证并发环境下的迭代操做不会出错。
util.concurrent中容器在迭代时,能够不封装在synchronized中,能够保证不抛异常,可是未必每次看到的都是"最新的、当前的"数据。算法
并发容器类简单介绍
ConcurrentHashMap
- 对应的非并发容器:HashMap
- 目标:代替Hashtable、synchronizedMap,支持复合操做
- 原理:JDK6中采用一种更加细粒度的加锁机制Segment“分段锁”,JDK8中采用CAS无锁算法。
CopyOnWriteArrayList
- 对应的非并发容器:ArrayList
- 目标:代替Vector、synchronizedList
- 原理:利用高并发每每是读多写少的特性,对读操做不加锁,对写操做,先复制一份新的集合,在新的集合上面修改,而后将新集合赋值给旧的引用,并经过volatile 保证其可见性,固然写操做的锁是必不可少的了。
CopyOnWriteArraySet
- 对应的费并发容器:HashSet
- 目标:代替synchronizedSet
- 原理:基于CopyOnWriteArrayList实现,其惟一的不一样是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法,其遍历当前Object数组,如Object数组中已有了当前元素,则直接返回,若是没有则放入Object数组的尾部,并返回。
ConcurrentSkipListMap
- 对应的非并发容器:TreeMap
- 目标:代替synchronizedSortedMap(TreeMap)
- 原理:Skip list(跳表)是一种能够代替平衡树的数据结构,默认是按照Key值升序的。Skip list让已排序的数据分布在多层链表中,以0-1随机数决定一个数据的向上攀升与否,经过”空间来换取时间”的一个算法。ConcurrentSkipListMap提供了一种线程安全的并发访问的排序映射表。内部是SkipList(跳表)结构实现,在理论上可以在O(log(n))时间内完成查找、插入、删除操做。
ConcurrentSkipListSet
- 对应的非并发容器:TreeSet
- 目标:代替synchronizedSortedSet
- 原理:内部基于ConcurrentSkipListMap实现
ConcurrentLinkedQueue
- 不会阻塞的队列
- 对应的非并发容器:Queue
- 原理:基于链表实现的FIFO队列(LinkedList的并发版本)
LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue
- 对应的非并发容器:BlockingQueue
- 特色:拓展了Queue,增长了可阻塞的插入和获取等操做
- 原理:经过ReentrantLock实现线程安全,经过Condition实现阻塞和唤醒
- 实现类:
- LinkedBlockingQueue:基于链表实现的可阻塞的FIFO队列
- ArrayBlockingQueue:基于数组实现的可阻塞的FIFO队列
- PriorityBlockingQueue:按优先级排序的队列