JUC-04-线程安全集合类

JUC-04-线程安全集合类

1. List 不安全

先看一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// java.util.ConcurrentModificationException
// 并发修改异常

public class unsafe {
public static void main(String[] args) {
// List<String> list = Arrays.asList("1", "2", "3");
// list.forEach(System.out::println);

// 并发下 ArrayList是不安全
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();
}

}
}

抛出异常:

1
2
// java.util.ConcurrentModificationException
// 并发修改异常

解决方案:

1
2
3
4
5
6
/*
解决方案:
1. List<String> list = new Vector<>();
2. List<String> list = Collections.synchronizedList(new ArrayList<>());
3. List<String> list = new CopyOnWriteArrayList<>();
*/

底层源码 :

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
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;


// CopyOnWrite 写入时复制(COW,计算机程序设计领域的优化策略)
// 多个线程调用的时候,List读取的时候,固定的;写入的时候(覆盖)
// 在写入的时候避免覆盖,造成数据问题!
// 读写分离



/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}

2. Set 不安全

先看一个Set不安全的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class unsafeSet {
public static void main(String[] args) {
Set<Object> 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();
}

}
}

抛出异常:

1
2
Exception in thread "3" java.util.ConcurrentModificationException
// 并发修改异常

解决方案:

1
2
3
// 解决方案
//1. Set<Object> set = Collections.synchronizedSet(new HashSet<>());
//2. Set<String> set = new CopyOnWriteArraySet<>();

hashSet的底层

1
2
3
4
5
6
7
8
public HashSet() {
map = new HashMap<>();
}

// set的add本质是就是map key是无法重复的
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

3. Map 不安全

先来看HashMap底层

1
2
3
4
5
6
7
8
9
// 加载因子
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

// 容量
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

mark

不安全举例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.zhuuu;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class UnsafeMap {
public static void main(String[] args) {

//map 默认两个值:(加载因子,初始化容量)
Map<String, String> map = new HashMap<>();

// 工作中不用HashMap
// 默认等价于什么?(16,0.75)

for (int i = 0; i < 30; i++) {
new Thread(()->{
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,5));
System.out.println(map);
},String.valueOf(i)).start();
}
}
}

抛出异常:

1
2
// java.util.ConcurrentModificationException
// 并发修改异常

解决方案:

1
2
3
//解决方案:
// 1. Map<String, String> map = new ConcurrentHashMap<>();
// 2. Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信