本文介绍并发List,有几点说明:
- 其在Java容器中的划分位置见[1]
- 根接口为List,其内元素允许为
NULL
- 并发List的常见使用场景不太用到迭代器,故本文对迭代器不作深入叙述
- 并发List可被用于“生产者-消费者模型”,当然“生产者-消费者模型”最常使用并发Queue
- 接下来介绍其常见的3个子类:
- CopyOnWriteArrayList
- Vector
- SynchronizedList
接下来对具体实现子类的介绍,主要基于以下几个维度:
- 是否有界,分为“设计是否有界”和“实际是否有界”,实际有“设计有界,实际有界”,“设计无界,实际无界”和“设计无界,实际有界,可称为假性无界”这3种情况
- 底层数据结构基于“数组”,还是“链表”
- 实现操作的线程安全策略
- 生成的迭代器性质[1]
一、CopyOnWriteArrayList
1、核心原理
- 设计无界,实际有界(在扩增数组时,目标大小如果大于等于
Integer.MAX_VALUE
,会抛出异常) - 基于数组
- 对于修改操作使用
ReentrantLock lock
锁实现操作的线程安全,即会阻塞加锁,默认是一个“非公平锁”,具体实现修改的策略是“实例变量array指向底层元素对象数组,修改时首先将当下对应的元素对象数组复制到新元素对象数组,然后在新元素对象数组上进行修改操作,最后将array赋值为指向新元素对象数组”;对于读取操作,不加锁,始终基于array指向的当前元素对象数组。综合以上两点,其适用场景如下:- 写少读多
- 集合不大,否则复制操作较为耗时
- 实时性要求不高,因为读取时可能读取到旧元素对象数组
- 生成特殊的“快照式”迭代器,其特殊性体现在:一般的“快照式”迭代器在生成迭代器时复制内容,而它在生成迭代器时不进行复制而是直接指向原内容,等到后续CopyOnWriteArrayList实例进行修改操作如上所述指向新内容时,它指向的内容才与CopyOnWriteArrayList实例指向的内容被动完成脱钩
2、构造参数
Collection<? extends E> c
:初始化元素来源集合E[] toCopyIn
:初始化元素来源集合
二、Vector
Vector有子类Stack,Stack中“栈数据结构”的方法(比如push()
,pop()
,peek()
等)通过调用Vector的方法实现。
1、核心原理
- 设计无界,实际有界
- 基于数组
- 使用
synchronized
实现读写时的线程安全,故属于同步容器
- 生成“快速失败”迭代器
2、构造参数
Collection<? extends E> c
:初始化元素来源集合int initialCapacity
:初始容量大小int capacityIncrement
:扩容增量大小
三、SynchronizedList
java.util.Collections
类中的内部类。
1、核心原理
- 基于所传入的List实例,有界性也依赖于它
- 使用
synchronized
实现操作的线程安全,故属于同步容器
- 生成所传入List实例的迭代器,故迭代器性质须具体情况具体分析
2、构造参数
List<E> list
:SynchronizedList实例所基于的底层List实例,注意其跟“初始化元素来源集合”不一样,后者在复制后就不再有关联Object mutex
:传入的锁对象