一、并发下,ArrayList类是不安全的
- 代码演示
package CollectionSafe; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * @author swaggyhang * @create 2023-07-02 17:26 */ public class Test01 { public static void main(String[] args) { List<String> list = new ArrayList<>(); for (int i = 1; i <= 10; i++) { new Thread(() -> { list.add(UUID.randomUUID().toString().substring(0, 5)); System.out.println(list); }, String.valueOf(i)).start(); } } }
- 上面代码会报错并发修改异常“java.util.ConcurrentModificationException”
二、解决方案
1. 使用Vector类【不推荐】
- Vector类的add方法是同步方法,但是效率很低
- 代码演示
package CollectionSafe; import java.util.List; import java.util.UUID; import java.util.Vector; /** * @author swaggyhang * @create 2023-07-02 17:26 */ public class Test01 { public static void main(String[] args) { // List<String> list = new ArrayList<>(); List<String> list = new Vector<>(); for (int i = 1; i <= 10; i++) { new Thread(() -> { list.add(UUID.randomUUID().toString().substring(0, 5)); System.out.println(list); }, String.valueOf(i)).start(); } } }
2. 使用Collections工具类
-
使用Collections.synchronizedList()方法将普通的ArrayList类转换为安全的集合类
-
代码演示
package CollectionSafe; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; /** * @author swaggyhang * @create 2023-07-02 17:26 */ public class Test01 { public static void main(String[] args) { // List<String> list = new ArrayList<>(); // List<String> list = new Vector<>(); List<String> list = Collections.synchronizedList(new ArrayList<>()); for (int i = 1; i <= 10; i++) { new Thread(() -> { list.add(UUID.randomUUID().toString().substring(0, 5)); System.out.println(list); }, String.valueOf(i)).start(); } } }
3. 使用CopyOnWriteArrayList类
-
写入时复制(简称:COW)是计算机领域的一种优化策略。底层源码如下:
-
多线程调用list时,读取的时候,是固定的,写入的时候,避免覆盖,造成数据问题(类似读写分离)
-
add()方法源码
-
代码演示
package CollectionSafe; import java.util.List; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; /** * @author swaggyhang * @create 2023-07-02 17:26 */ public class Test01 { public static void main(String[] args) { // List<String> list = new ArrayList<>(); // List<String> list = new Vector<>(); // List<String> list = Collections.synchronizedList(new ArrayList<>()); List<String> list = new CopyOnWriteArrayList<>(); for (int i = 1; i <= 10; i++) { new Thread(() -> { list.add(UUID.randomUUID().toString().substring(0, 5)); System.out.println(list); }, String.valueOf(i)).start(); } } }
三、并发下,HashSet类是不安全的
-
HashSet本质就是HashMap,其构造器生成一个map对象
-
add()方法源码
-
代码演示
package CollectionSafe; import java.util.HashSet; import java.util.Set; import java.util.UUID; /** * @author swaggyhang * @create 2023-07-04 10:42 */ public class Test02 { public static void main(String[] args) { Set<String> set = new HashSet<>(); for (int i = 1; i <= 100; i++) { new Thread(() -> { set.add(UUID.randomUUID().toString().substring(0, 5)); System.out.println(set); }, String.valueOf(i)).start(); } } }
-
上面代码会报错并发修改异常“java.util.ConcurrentModificationException”
四、解决方案
1. 使用Collections工具类
-
使用Collections.synchronizedSet()方法将普通的HashSet类转换为安全的集合类
package CollectionSafe; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.UUID; /** * @author swaggyhang * @create 2023-07-04 10:42 */ public class Test02 { public static void main(String[] args) { // Set<String> set = new HashSet<>(); Set<String> set = Collections.synchronizedSet(new HashSet<>()); for (int i = 1; i <= 100; i++) { new Thread(() -> { set.add(UUID.randomUUID().toString().substring(0, 5)); System.out.println(set); }, String.valueOf(i)).start(); } } }
2. 使用CopyOnWriteArraySet类
- CopyOnWriteArraySet底层还是使用CopyOnWriteArrayList那一套逻辑
package CollectionSafe; import java.util.Set; import java.util.UUID; import java.util.concurrent.CopyOnWriteArraySet; /** * @author swaggyhang * @create 2023-07-04 10:42 */ public class Test02 { public static void main(String[] args) { // Set<String> set = new HashSet<>(); // Set<String> set = Collections.synchronizedSet(new HashSet<>()); Set<String> set = new CopyOnWriteArraySet<>(); for (int i = 1; i <= 100; i++) { new Thread(() -> { set.add(UUID.randomUUID().toString().substring(0, 5)); System.out.println(set); }, String.valueOf(i)).start(); } } }
- 构造器源码
- add()方法源码
五、并发下,HashMap类是不安全的
-
代码演示
package CollectionSafe; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * @author swaggyhang * @create 2023-07-04 11:08 */ public class Test03 { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); for (int i = 1; i <= 10; 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”
六、解决方案
1. 使用Collections工具类
- 使用Collections.synchronizedMap()方法将普通的HashMap类转换为安全的集合类
package CollectionSafe; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * @author swaggyhang * @create 2023-07-04 11:08 */ public class Test03 { public static void main(String[] args) { // Map<String, String> map = new HashMap<>(); Map<String, String> map = Collections.synchronizedMap(new HashMap<>()); for (int i = 1; i <= 10; i++) { new Thread(() -> { map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 5)); System.out.println(map); }, String.valueOf(i)).start(); } } }
2. 使用ConcurrentHashMap类
-
代码演示
package CollectionSafe; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; /** * @author swaggyhang * @create 2023-07-04 11:08 */ public class Test03 { public static void main(String[] args) { // Map<String, String> map = new HashMap<>(); // Map<String, String> map = Collections.synchronizedMap(new HashMap<>()); Map<String, String> map = new ConcurrentHashMap<>(); for (int i = 1; i <= 10; i++) { new Thread(() -> { map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 5)); System.out.println(map); }, String.valueOf(i)).start(); } } }
-
研究ConcurrentHashMap底层源码!!