目录
不安全的集合类
多线程下ArrayList、SetList、HashMap这些常用的集合都不安全了。原因在于这些集合底层没有使用volatile关键字和CAS机制。当它们在多线程下执行时,时不时会爆出ConcurrentModificationException(并发修改异常)。
解决此问题需要加上volatile和CAS操作,JUC中给我们提供了基于上述的并发集合类,接下来我们就来学习下。
CopyOnWriteArrayList
List集合在单线程时是安全的,但多线程的情况下是不安全的。
public class ListTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i <= 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
下面报出ConcurrentModificationException(并发修改异常)
解决List集合不安全的问题有三种解决办法
//方法一:Vector
List<String> list = new Vector<>();
//方法二:Collections
List<String> list =Collections.synchronizedList(new ArrayList<>());
//方法三:JUC的CopyOnWriteArrayList
List<String> list = new CopyOnWriteArrayList<>();
之所以用CopyOnWriteArrayList是因为它的底层用的是CopyOnWrite,即写入时复制。
COW是计算机程序设计领域的一种优化策略,在写入时先复制再写,避免了覆盖问题的发生。
Vector底层用的是Synchronized,而CopyOnWrite底层是Lock锁。Lock的效率比Sychronized高
CopyOnWriteArraySet
Set集合在多线程的情况下同样不安全,我们通过JUC提供的CopyOnWriteAarraySet来解决这个问题。
public class SetTest {
public static void main(String[] args) {
Set<String> set = new CopyOnWriteArraySet<>();
for (int i = 0; i < 10; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(set);
},String.valueOf(i)).start();
}
}
}
由源码可知HashSet的底层是Map集合
hashset详情可参考https://blog.csdn.net/Delicious_Life/article/details/105103227
ConcurrentHashMap
针对HashMap的解决方案是ConcurrentHashMap
// ConcurrentModificationException
public class MapTest {
public static void main(String[] args) {
// 默认等价于什么? new HashMap<>(16,0.75);
// Map<String, String> map = new HashMap<>();
Map<String, String> map = new ConcurrentHashMap<>();
for (int i = 1; i <= 30; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(
0, 5));
System.out.println(map);
}, String.valueOf(i)).start();
}
}
}
ConcurrentHashMap详细可参考https://blog.csdn.net/Delicious_Life/article/details/107393757