https://www.cnblogs.com/lkxsnow/p/12247524.html
· Vector
Vector大部分方法和ArrayList都是相同的,只是加上了synchronized关键字(同步在this上),这种方式严重影响效率(实际读写性能和Collections.synchronizedList相似),因此,不再推荐使用Vector了。
· Collections.synchronizedList
List list = Collections.synchronizedList(new ArrayList());
转换包装后的list可以实现add,remove,get等操作的线程安全性,但是对于迭代操作,Collections.synchronizedList并没有提供相关机制,所以迭代时需要对包装后的list(敲黑板,必须对包装后的list进行加锁,锁其他的不行)进行手动加锁,使用方式如下
List list = Collections.synchronizedList(new ArrayList());
//必须对list进行加锁
synchronized (list) {
Iterator i = list.iterator();
while (i.hasNext())
foo(i.next());
}
这个地方要注意两个地方:
迭代操作必须加锁,可以使用synchronized关键字修饰;
synchronized持有的监视器对象必须是synchronized (list),即包装后的list,使用其他对象如synchronized (new Object())会使add,remove等方法与迭代方法使用的锁不一致,无法实现完全的线程安全性。
Collections.synchronizedList生成了特定同步的SynchronizedCollection,生成的集合每个同步操作都是持有mutex这个锁,所以再进行操作时就是线程安全的集合了。(同步在mutex上)
·CopyOnWriteArrayList
是java并发包里类,用可重入锁
每次修改都会生成一个新的Array,同时利用Arrays.copyOf复制,最后更新
修改的时候加锁,读的时候不加锁,读写分离
但是会有一段时间的数据更新延迟,不是强同步
适用读多写少的非严格同步环境
·对比
CopyOnWriteArrayList的写操作与Vector的遍历操作性能消耗尤其严重,遍历场景适用Collections.synchronizedList。
CopyOnWriteArrayList适用于读操作远远多于写操作的场景,且容许一定时间的数据更新延迟,即在搞并发读的时候可能会读到旧数据,这在一些严格的场景是不适用的。
Vector读写性能可以和Collections.synchronizedList比肩,但Collections.synchronizedList不仅可以包装ArrayList,也可以包装其他List,扩展性和兼容性更好。一般不推荐Vector。