文章目录
-
- ArrayList不是线程安全的,使用一个案例演示
-
- 需要线程安全怎么办?
-
ArrayList不是线程安全的,使用一个案例演示
import java.util.List;
//线程任务类
public class CollectionTask implements Runnable {
private List<String> list;
public CollectionTask(List<String> list) {
this.list = list;
}
@Override
public void run() {
//在任务中插入名字
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add(Thread.currentThread().getName());
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//测试类
public class ArrayListSafetyTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
//list = Collections.synchronizedList(list);
CollectionTask task = new CollectionTask(list);
for (int i = 0; i < 50; i++) {
new Thread(task).start();
}
//等待线程执行
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//遍历链表
for (String str : list
) {
System.out.println(str);
}
}
}
结果分析
- 问题就是遍历链表出现null值, 我们看看源码分析一下这是为什么
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
//添加一次元素就会size++一次
elementData[size++] = e;
return true;
}
- 问题就出在size++上, 多个线程同时给一个位置添加元素, 导致size++了, 但是数据覆盖了, 所以就会出现空的位置
需要线程安全怎么办?
- 使用Collections.synchronizedList(list)或者Vector<>()
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//测试类
public class ArrayListSafetyTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
//重点
list = Collections.synchronizedList(list);
CollectionTask task = new CollectionTask(list);
for (int i = 0; i < 50; i++) {
new Thread(task).start();
}
//等待线程执行
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//遍历链表
for (String str : list
) {
System.out.println(str);
}
}
}
源码分析其为何安全?