ArrayList线程不安全
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; /** * list集合线程不安全 * add()为无锁状态,意味着每一个线程都可以在同一时间去抢夺add使用 * 这就会导致在同一时间,多个线程对同一地址进行写入数据, * 并且在写的同时,还会有大批线程来读取数据,这就 * 会出现一个异常ConcurrentModificationException(并发修改异常) * * * 解决方法 1 使用Vector 他是ArrayList的前生 使用的线程同步 * 解决方法2 使用Collections.synchronizedList(new ArrayList<>()); 将其转换为线程安全的集合 * 解决方法3 使用juc中的CopyOnWriteArrayList 读写分离技术 */ public class ConcurrentListDemo { public static void main(String[] args) { List<Object> list = new CopyOnWriteArrayList();//Collections.synchronizedList(new ArrayList<>());//new ArrayList<>(); for (int i = 0; i < 30; i++) { new Thread(()->{ list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); }).start(); } // list.add("123"); // list.add("123"); // list.add("123"); // System.out.println(list); } }
HashSet线程不安全
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.UUID; import java.util.concurrent.CopyOnWriteArraySet; /** * set集合线程不安全 问题与list相同 没有线程同步 * HashSet的底层是HashMap *但是CopyOnWriteArraySet的底层是使用CopyOnWriteArrayList<E>(); *return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false : * addIfAbsent(e, snapshot); * 以上代码去重 * * 防止其他线程add 再去校验有无重复项 * if (snapshot != current) { * // Optimize for lost race to another addXXX operation * int common = Math.min(snapshot.length, len); * for (int i = 0; i < common; i++) * if (current[i] != snapshot[i] && eq(e, current[i])) * return false; * if (indexOf(e, current, common, len) >= 0) * return false; * } * * * public CopyOnWriteArraySet() { * al = new CopyOnWriteArrayList<E>(); * } * * * public HashSet() { * map = new HashMap<>(); *} * * public boolean add(E e) { * return map.put(e, PRESENT)==null; 添加的值是一个常量Object * } * * * 解决方法 * 1.Collections.synchronizedSet(new HashSet<>()); * 2.juc CopyOnWriteArraySet() 读写分离技术 */ public class ConcurrentSetDemo { public static void main(String[] args) { Set set = new CopyOnWriteArraySet();//Collections.synchronizedSet(new HashSet<>());//new HashSet(); for (int i = 0; i < 30; i++) { new Thread(()->{ set.add(UUID.randomUUID().toString()); System.out.println(set); }).start(); } } }
HashMap线程不安全
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * HashMap 同样线程不安全 * * HashMap 底层使用的 是 Node类型的数组 Node类型的链表 以及红黑树 * static class Node<K,V> implements Map.Entry<K,V> { * final int hash; * final K key; * V value; * Node<K,V> next; *为单向链表 * * 创建默认大小是 16 ,负载系数(负载因子是0.75) 当单个链表长度达到8时会转换为红黑树 * * * * Node<K,V>[] tab; Node<K,V> p; int n, i; * 若表为空则初始化一个表,或者扩建表 * if ((tab = table) == null || (n = tab.length) == 0) * n = (tab = resize()).length; * //将总长度减1(16-1)=15 与 hash(若为1) 做与运算 1111 & 0001 结果 为 0001 * if ((p = tab[i = (n - 1) & hash]) == null) 从表中取值 若此索引为空 * tab[i] = newNode(hash, key, value, null); //将数据添加到此索引 * else { //经过以上判断 若 p查到啦则走下面程序 (所以p有值) * Node<K,V> e; K k; * //判断若 p的hash值等于带添加的hash并且 key值相等 * if (p.hash == hash && * ((k = p.key) == key || (key != null && key.equals(k)))) * //则覆盖 * e = p; * * 后面是对树的处理没有研究 * * * * 解决线程不安全 * * 方法1 : Collections.synchronizedMap(new HashMap<>()) * 方法2 : ConcurrentHashMap(); */ public class ConcurrentMapDemo { public static void main(String[] args) { Map<Object, Object> hashMap = new ConcurrentHashMap<>();//Collections.synchronizedMap(new HashMap<>());//new HashMap<>(); for (int i = 0; i < 30; i++) { new Thread(()->{ hashMap.put(UUID.randomUUID().toString(),"123"); System.out.println(hashMap); }).start(); } } }
最后
以上就是清新皮皮虾最近收集整理的关于JUC解决多线程集合线程不安全,以及ConcurrentModificationException(并发修改异常)的全部内容,更多相关JUC解决多线程集合线程不安全内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复