不安全举例
以LinkedList为例,运行一下代码
public static void main(String[] args) {
List<String> list = new LinkedList<>();
for (int i = 0; i < 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list.toString());//在添加的时候,取值这时候就会发生并发修改的问题
},i+"").start();
}
}
结果,可能会正常执行,基本都会报并发修改异常
解决方法
1、Vector(古老效率低)
public static void main(String[] args) {
/*List<String> list = new LinkedList<>();*/
List<String> list = new Vector<>();
for (int i = 0; i < 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list.toString());
},i+"").start();
}
}
这时候运行正常
从源码中可以看到
其方法都是加了synchronize锁的,以此保证线程安全,这样也带来的效率低下的问题
2、利用Collections(同样古老)
public static void main(String[] args) {
/*List<String> list = new LinkedList<>();*/
List<String> list = Collections.synchronizedList(new LinkedList<>());
for (int i = 0; i < 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(Thread.currentThread().getName()+ ":"+ list.toString());
},i+"").start();
}
}
运行结果
3、CopyOnWriteArrayList(写时复制)
public static void main(String[] args) {
/*List<String> list = new LinkedList<>();*/
/*List<String> list = new Vector<>();*/
/*List<String> list = Collections.synchronizedList(new LinkedList<>());*/
List<String> list = new CopyOnWriteArrayList<>();
for (int i = 0; i < 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(Thread.currentThread().getName()+ ":"+ list.toString());
},i+"").start();
}
}
其原理图
HashMap 和HashSet也同样拥有一样的问题
这时候我们分别用ConcurrentHashMap和CopyOnWriteArraySet就能解决问题。
Map<String,String> map = new ConcurrentHashMap<>();
Set<String> set = new CopyOnWriteArraySet<>();