一.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。