在java中,存在很多集合,比如ArrayList、LinkedList、HashSet、HashMap等。如何保证它们在多线程下的集合安全性呢?
List集合
测试
public class ListTest {
public static void main(String[] args) {
// ArrayList<String> list = new ArrayList<>();
// 1. List<String> list = new Vector<>();
// 2. List<String> list = Collections.synchronizedList(new ArrayList<>());
// 3. List<String> list = new CopyOnWriteArrayList<>();
ArrayList<String> list = new ArrayList<>();
for (int i = 1; i <= 30; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
结果
报错:java.util.ConcurrentModificationException
解决方案
使用List list = new Vector<>();
实际是使用了synchronized实现加锁使线程安全。
使用List list = Collections.synchronizedList(new ArrayList<>());
实际也是新建一个synchronized锁的List。
使用List list = new CopyOnWriteArrayList<>();
实际是使用ReentrantLock锁,先对需要写入的数据进行复制,写完之后再合并,实现了读写分离,读的是同一个数据,而写的是不同的数据,避免写入混乱。
Set集合
测试
public class SetTest {
public static void main(String[] args) {
// Set<String> set = new HashSet<>();
// 1. Set<String> set = Collections.synchronizedSet(new HashSet<>());
// 2. Set<String> set = new CopyOnWriteArraySet();
Set<String> set = new HashSet<>();
for (int i = 1; i <= 30; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(set);
},String.valueOf(i)).start();
}
}
}
结果
报错:java.util.ConcurrentModificationException
解决方案
使用Set set = Collections.synchronizedSet(new HashSet<>());
新建一个synchronized锁的Set。
使用Set set = new CopyOnWriteArraySet();
本质是使用ReentrantLock锁,先对需要写入的数据进行复制,写完之后再合并,实现了读写分离,读的是同一个数据,而写的是不同的数据,避免写入混乱。
HashSet的底层就是HashMap
add方法本质就是map,因为map的key不能重复,因此set里的键也不重复。
Map集合
测试
public class MapTest {
public static void main(String[] args) {
//默认等价于什么? Map<String, Object> map = new HashMap<String, Object>(16,0.75);
//初始化容量 16 / 加载因子 0.75
// Map<String, String> map = new HashMap<String, Object>();
// 1. Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
// 2. Map<String, String> map = new ConcurrentHashMap<>();
Map<String, String> map = new HashMap<String, String>();
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();
}
}
}
结果
报错:java.util.ConcurrentModificationException
解决方案
使用Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
新建一个synchronized锁的Map。
使用Map<String, String> map = new ConcurrentHashMap<>();