在java的项目开发中,我们工作中使用最多的集合应该就是ArrayList了,
但是你可知ArrayList是线程不安全的,平时我们使用时都是单线程或者线程数比较少的情况,
这种情况ArrayList一般都不会出现问题,但是线程一旦多起来,问题就很容易爆发了
如下面的多线程案例
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class ListTest {
private static final int threadNum = 20;
static List list =new ArrayList();
static CountDownLatch latch = new CountDownLatch(20);
public static void main(String[] args) {
for (int i = 0; i < threadNum; i++) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
list.add(i);
}
latch.countDown();
}
});
thread.start();
}
try {
latch.await();//等待所有线程完成
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("list中总数量===="+list.size());
}
}
正常结果应该打印20000,可是每次运行的结果确实抛出异常java.lang.ArrayIndexOutOfBoundsException
这是什么原因呢?
这是因为ArrayList底层是数组,每次add时,执行 element[i++]=a,
而element[i++]=a在cup层是分两步进行的
1. element[i]=a
2. i=i+1
但由于多线程运行时,假设数组的长度一开始等于2,i等于1,数组还剩一个元素可放入,A线程刚进入add方法时,还没来得及执行步骤1, cup就让他暂停,此时线程B运行了,依然是i=1,执行1、2步骤后,i变成了2,
等到A线程运行1时,element[2]=a 就发生越界了。
这就是线程不安全了,假设线程在进入add之前就已经发现数组长度不够,ArrayList就会进行扩容,就不会发生这种情况了
怎么解决呢
这就是本次的主角Vector上场了
只需要就static List list =new ArrayList();换成 static List list =new Vector();就可以保证线程安全了