CopyOnWriteArrayList与Collections.synchronizedList的性能对比
来源:互联网 发布:工业视觉软件 编辑:程序博客网 时间:2024/05/21 04:17
一 、ArrayList
ArrayList是非线性安全,此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。即在一方在便利列表,而另一方在修改列表时,会报ConcurrentModificationException错误。而这不是唯一的并发时容易发生的错误,在多线程进行插入操作时,由于没有进行同步操作,容易丢失数据。
public boolean add(E e) {ensureCapacity(size + 1); // Increments modCount!!elementData[size++] = e;//使用了size++操作,会产生多线程数据丢失问题。return true; }
因此,在开发过程当中,ArrayList并不适用于多线程的操作。
二、Vector
从JDK1.0开始,Vector便存在JDK中,Vector是一个线程安全的列表,采用数组实现。其线程安全的实现方式是对大部分操作都加上了synchronized关键字,这种方式严重影响效率,因此,不再推荐使用Vector了,Stackoverflow当中有这样的描述:Why is Java Vector class considered obsolete or deprecated?。
三、Collections.synchronizedList & CopyOnWriteArrayList
CopyOnWriteArrayList和Collections.synchronizedList是实现线程安全的列表的两种方式。两种实现方式分别针对不同情况有不同的性能表现,其中CopyOnWriteArrayList的写操作性能较差,而多线程的读操作性能较好。而Collections.synchronizedList的写操作性能比CopyOnWriteArrayList在多线程操作的情况下要好很多,而读操作因为是采用了synchronized关键字的方式,其读操作性能并不如CopyOnWriteArrayList。因此在不同的应用场景下,应该选择不同的多线程安全实现类。
3.1 Collections.synchronizedList
public static <T> List<T> synchronizedList(List<T> list) {return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<T>(list) : new SynchronizedList<T>(list));//根据不同的list类型最终实现不同的包装类。 }
Collections.synchronizedList的源码可知,其实现线程安全的方式是建立了list的包装类,其中,SynchronizedList对部分操作加上了synchronized关键字以保证线程安全。但其iterator()操作还不是线程安全的。部分SynchronizedList的代码如下:
public E get(int index) { synchronized(mutex) {return list.get(index);} }public E set(int index, E element) { synchronized(mutex) {return list.set(index, element);} }public void add(int index, E element) { synchronized(mutex) {list.add(index, element);} }public ListIterator<E> listIterator() { return list.listIterator(); // Must be manually synched by user 需要用户保证同步,否则仍然可能抛出ConcurrentModificationException }public ListIterator<E> listIterator(int index) { return list.listIterator(index); // Must be manually synched by user <span style="font-family: Arial, Helvetica, sans-serif;">需要用户保证同步,否则仍然可能抛出ConcurrentModificationException</span> }
3.2 CopyOnWriteArrayList
没有加任何同步关键字,根据以上写操作的代码可知,其每次写操作都会进行一次数组复制操作,然后对新复制的数组进行些操作,不可能存在在同时又读写操作在同一个数组上(不是同一个对象),而读操作并没有对数组修改,不会产生线程安全问题。Java中两个不同的引用指向同一个对象,当第一个引用指向另外一个对象时,第二个引用还将保持原来的对象。
其中setArray()操作仅仅是对array进行引用赋值。Java中“=”操作只是将引用和某个对象关联,假如同时有一个线程将引用指向另外一个对象,一个线程获取这个引用指向的对象,那么他们之间不会发生ConcurrentModificationException,他们是在虚拟机层面阻塞的,而且速度非常快,是一个原子操作,几乎不需要CPU时间。
3.3 Collections.synchronizedList & CopyOnWriteArrayList在读写操作上的差距
测试代码:package rte;import org.junit.Test;import java.util.*;import java.util.concurrent.*;/** * Created with IntelliJ IDEA. * User: yangzl2008 * Date: 14-9-18 * Time: 下午8:36 * To change this template use File | Settings | File Templates. */public class Test02 { private int NUM = 10000; private int THREAD_COUNT = 16; @Test public void testAdd() throws Exception { List<Integer> list1 = new CopyOnWriteArrayList<Integer>(); List<Integer> list2 = Collections.synchronizedList(new ArrayList<Integer>()); CountDownLatch add_countDownLatch = new CountDownLatch(THREAD_COUNT); ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT); int add_copyCostTime = 0; int add_synchCostTime = 0; for (int i = 0; i < THREAD_COUNT; i++) { add_copyCostTime += executor.submit(new AddTestTask(list1, add_countDownLatch)).get(); } System.out.println("CopyOnWriteArrayList add method cost time is " + add_copyCostTime); for (int i = 0; i < THREAD_COUNT; i++) { add_synchCostTime += executor.submit(new AddTestTask(list2, add_countDownLatch)).get(); } System.out.println("Collections.synchronizedList add method cost time is " + add_synchCostTime); } @Test public void testGet() throws Exception { List<Integer> list = initList(); List<Integer> list1 = new CopyOnWriteArrayList<Integer>(list); List<Integer> list2 = Collections.synchronizedList(list); int get_copyCostTime = 0; int get_synchCostTime = 0; ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT); CountDownLatch get_countDownLatch = new CountDownLatch(THREAD_COUNT); for (int i = 0; i < THREAD_COUNT; i++) { get_copyCostTime += executor.submit(new GetTestTask(list1, get_countDownLatch)).get(); } System.out.println("CopyOnWriteArrayList get method cost time is " + get_copyCostTime); for (int i = 0; i < THREAD_COUNT; i++) { get_synchCostTime += executor.submit(new GetTestTask(list2, get_countDownLatch)).get(); } System.out.println("Collections.synchronizedList get method cost time is " + get_synchCostTime); } private List<Integer> initList() { List<Integer> list = new ArrayList<Integer>(); int num = new Random().nextInt(1000); for (int i = 0; i < NUM; i++) { list.add(num); } return list; } class AddTestTask implements Callable<Integer> { List<Integer> list; CountDownLatch countDownLatch; AddTestTask(List<Integer> list, CountDownLatch countDownLatch) { this.list = list; this.countDownLatch = countDownLatch; } @Override public Integer call() throws Exception { int num = new Random().nextInt(1000); long start = System.currentTimeMillis(); for (int i = 0; i < NUM; i++) { list.add(num); } long end = System.currentTimeMillis(); countDownLatch.countDown(); return (int) (end - start); } } class GetTestTask implements Callable<Integer> { List<Integer> list; CountDownLatch countDownLatch; GetTestTask(List<Integer> list, CountDownLatch countDownLatch) { this.list = list; this.countDownLatch = countDownLatch; } @Override public Integer call() throws Exception { int pos = new Random().nextInt(NUM); long start = System.currentTimeMillis(); for (int i = 0; i < NUM; i++) { list.get(pos); } long end = System.currentTimeMillis(); countDownLatch.countDown(); return (int) (end - start); } }}
一次输出:
CopyOnWriteArrayList add method cost time is 15294Collections.synchronizedList add method cost time is 15CopyOnWriteArrayList get method cost time is 5Collections.synchronizedList get method cost time is 6
写操作:在线程数目增加时CopyOnWriteArrayList的写操作性能下降非常严重,而Collections.synchronizedList虽然有性能的降低,但下降并不明显。
4 结论
转自: http://blog.csdn.net/yangzl2008/article/details/39456817#
- CopyOnWriteArrayList与Collections.synchronizedList的性能对比
- CopyOnWriteArrayList与Collections.synchronizedList的性能对比
- CopyOnWriteArrayList与Collections.synchronizedList的性能对比
- CopyOnWriteArrayList与Collections.synchronizedList的性能对比
- CopyOnWriteArrayList与Collections.synchronizedList的性能对比
- CopyOnWriteArrayList与Collections.synchronizedList的性能对比
- CopyOnWriteArrayList与Collections.synchronizedList的性能对比
- Collections.synchronizedList & CopyOnWriteArrayList
- CopyOnWriteArrayList与Collections.synchronizedMap性能比较
- CopyOnWriteArrayList与Collections.synchronizedMap性能比较
- CopyOnWriteArrayList与Collections.synchronizedMap性能比较
- CopyOnWriteArrayList与Collections.synchronizedMap性能比较
- 线程安全的Collections.synchronizedList
- Collections.synchronizedList
- Collections.synchronizedList
- Collections.synchronizedList
- 【集合类型的并发】Collections.synchronizedList
- Collections.synchronizedList()不同锁造成的陷阱
- 编译错误
- C#控制台基础 helloworld之 派生类出现同名方法,通过调用基类的方法输出
- spring-data-elasticsearch api
- 关于Android的layout_weight
- 解决方案-支持各种屏幕密度
- CopyOnWriteArrayList与Collections.synchronizedList的性能对比
- Shallow and Deep Convolutional Networks for Saliency Prediction
- iOS开发:相对路径与相对工程名
- 做SEO的我们是必要先了解看搜索引擎的工作原里
- android标题栏详细讲解(1,2)
- Linux IPC之Socket网络编程基础篇
- PHP中遍历数组元素的几种方法
- Java关键字final、static使用总结
- SQL数据库备份恢复助手 V2.7.6 官方免费版