大厂面试题:我们知道ArrayList是线程不安全的,请编码写一个不安全的案例并给出解决方案?
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ContainerNotSafeDemoOne {
public static void main(String[] args) {
// ArrayList是一个线程不安全的类
List
for (int i = 0; i < 30; i++) {
new Thread(() -> {
arrList.add(UUID.randomUUID().toString());
System.out.println(arrList.toString());
}, String.valueOf(i)).start();
}
}
}
程序执行结果如下:报java.util.ConcurrentModificationException异常
一个线程正在写,另一个线程过来抢占资源,会造成数据不一致,进而报并发修改异常。
ArrayList改成Vector集合类
import java.util.List;
import java.util.UUID;
import java.util.Vector;
public class ContainerSafeDemoOne {
public static void main(String[] args) {
List
for (int i = 0; i < 30; i++) {
new Thread(() -> {
arrList.add(UUID.randomUUID().toString());
System.out.println(arrList.toString());
}, String.valueOf(i)).start();
}
}
}
使用Collections工具类创建同步集合类
import java.util.*;
public class ContainerSafeDemoTwo {
public static void main(String[] args) {
List
for (int i = 0; i < 30; i++) {
new Thread(() -> {
arrList.add(UUID.randomUUID().toString());
System.out.println(arrList.toString());
}, String.valueOf(i)).start();
}
}
}
使用并发编程类CopyOnWriteArrayList替换ArrayList
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
public class ContainerSafeDemoThree {
public static void main(String[] args) {
List
for (int i = 0; i < 30; i++) {
new Thread(() -> {
arrList.add(UUID.randomUUID().toString());
System.out.println(arrList.toString());
}, String.valueOf(i)).start();
}
}
}
CopyOnwriteArrayList容器即写时复制容器。往一个容器添加元素的时候,不直接往当前容器Object[]添加,而是先将当前容器Object []进行copy,复制出一个新的容器object[] newElements,然后往新的容器Object [] newElements里添加元素,添加元素之后,再将原容器的引用指向新的容器setArray(newElements);这样做的好处是可以对CopyOnWrite容器进行并发读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写是不同的容器。
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}