我有一段关于ArrayLisy和Vector线程安全的代码,如下:
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
public class SynchronizedCollectionsTest {
static List<Integer> list = new ArrayList<Integer>(20);
static List<Integer> vector = new Vector<Integer>();
public static void main(String[] args) {
Thread thread1 = new Thread() {
public void run() {
for (int i = 0; i < 10; i++) {
list.add(list.size(), i);
vector.add(vector.size(), i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
};
Thread thread2 = new Thread() {
public void run() {
for (int i = 0; i < 10; i++) {
list.add(list.size(), i);
vector.add(vector.size(), i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
};
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
System.out.println(e);
}
System.out.println(list);
System.out.println(vector);
}
}
现在想请教各位,list集合是如何产生出null的?
你看这段代码:
List list = new ArrayList();
list.add(0, 1);
list.add(0, 1);
list.add(2, 2);
System.out.println(list);
打印出来的结果是[1, 1, 2]
在同一位置赋值两次,下个位置不是null是1,从源代码看就是将1往后挪动了一个位置。
还有,如果中间某一个位置没有赋值的话,就抛出 java.lang.IndexOutOfBoundsException。
我是不是钻牛角尖了啊,呵呵
你理解错了
你这样直接add是没有错
因为add方法里面已经帮你做了往后移动数组的操作了
源代码里面的操作,移动数组和赋值操作分开的
所以先移动两次,再赋值的话,两次都是赋给了同一位置,后面那个位置没有被赋值
所以是空
你要看源代码 看外面的话,由于封装了很多,没法理解的
其实这个不需要太深的去研究
你只要记得ArrayList是非线程安全的,在add的时候需要加锁就ok了
我运行了下
正常的哈……
怎么会打印出null?
嗯
你给list的add操作加个同步锁
List类的add方法是非同步的 线程不安全
意思就是两个线程不能同时add
Vector是线程安全的
不需要加锁
刚看了下源代码
在ArrayList的add操作中
add(int index, Object element)
有一句赋值操作,elementData[index] = element;
所以有可能是两个add操作并发时 把两个element赋值到同一个index位置了
但是在该方法中,有size++ list长度依旧会+2
所以导致其中会有一个是null 没有被赋值
我也是刚看的源码
不知道对你有没有帮助
补充
源代码:
public void add(int index, Object element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
ensureCapacity(size+1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
这个是源码
ensureCapacity(size+1); 这个是给List多加一个存储单元
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
这个是把之前的List,从index的位置开始,往后移动一个位置
elementData[index] = element; 这个就是赋值
size++; 长度加一
造成null主要是由于
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
和 elementData[index] = element;
移动肯定是两次,赋值也是两次,但是赋给了同一个位置
我发现我还是没怎么说清楚
说的有一点小问题
不过不影响你理解
你理解没
要是没理解 我再给你说一遍……
你自己在纸上模拟一下怎么操作的就明白了
很简单的……
当前位置被赋值了
下个位置没有被赋值 变成null了