多线程中集合不安全问题及解决方案

it2024-04-10  46

在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<>();

最新回复(0)