java基础----arraylist与vector

一.arraylist和vector的异同

  相同:

  1.他们的底层都是通过数组实现的。

  2.在内存中,元素与元素之间不能存有间隔,也就是说,它们都需要申请一个连续的内存空间去存放数据。

  3.数组通过下标能快速定位到元素,因此查询能力比较强大,但是如果是插入或者删除元素,在插入或删除的位置往后的元素都需要移动,因此代价较大,性能较低。

  不同:

  1.arraylist是线程不安全的,而vector通过synchronized来实现同步,所以它是线程安全的。  

  2.如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势,因为不需要过多的扩容操作。

二.如何解决arrayList线程不安全的问题?

  先上一段代码

import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

public class ArrayListDemo {
    public static void main(String[] args) {
        //List<String> list = new ArrayList<String>();
        //List<String> list = Collections.synchronizedList(new ArrayList<String>());
        List<String> list = new CopyOnWriteArrayList<String>();

        //使用arrayList的时候,这里会报异常java.util.ConcurrentModificationException
        for(int i = 1; i < 30; i++){
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },"test"+i).start();
        }
    }
}

  在多线程并发的环境下,对arrayList进行add操作的话,是会出现预期之外的结果,甚至报出异常的。而想要解决这个问题,其实有如下几种方法。

  1.使用vector类,这种方法其实不建议是用,因为vector类是用了synchornized来保证了线程安全,但是其并发性将会大大地下降。

  2.使用Collections类里面的synchronizedList,虽然都使用了synchornized,但是synchronizedList是通过同步代码块实现线程安全的,在效率上来看,比vector更具有优势,但是这个也不是最推荐使用的。

  3.使用copyOnWriteArrayList,它才用了写时复制来保证了效率同时也保证线程的安全性,其原理是,线程在修改一个对象的时候,会先争夺reentrantLock,拿到锁资源后,会先拷贝一个副本到自己的工作内存中,然后对这个副本进行复制,并且长度加1,然后把新的元素添加在新的list的尾部,最后将变量指向新的list。这样只针对写操作上锁,并且写操作是针对副本操作的,并不会影响到读操作,实现了读写分离,因此读操作是可以并发进行的。这种模式下面,整个并发效率将得到很好的保证。

  同理,在set的场景中,也建议使用copyOnWriteArraySet来解决线程不安全问题。而在map的场景下,建议使用concurrentHashMap。