1 线程安全的集合

  • Vector

    为什么Vecter是线程安全的呢?查看源代码:

    Vector源码分析

    从上面的代码可以看到,每个方法都加上了synchronized关键字,所以它是线程安全的。但是因为它的所有方式都加上了synchronized关键字,那么无论你是否需要对其进行多线程访问时,它都会对其进行锁定,执行效率会很低。现在已经弃用

  • HashTable

    HashTableVector类似,都是在每个方法上加上synchronized关键字来达到线程安全的目的。我们可以从下面的源代码可以看出:

    HashTable源代码分析

2 java.util.concurrent下的线程安全集合

java.util包下有一个concurrent包,下面的集合都是线程安全的集合,当需要使用线程来操作集合时,就调用该包下面的集合。下面看一段线程不安全的集合代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.LinkedList;
import java.util.List;

public class ThreadSafe {
public static void main(String[] args) throws InterruptedException {
List<String> list = new LinkedList<>();
Thread thread1 =new Thread(()->{
for (int i = 0; i < 1000; i++) {
list.add("add");
}
});
Thread thread2 = new Thread(()->{
for (int i = 0; i < 1000; i++) {
list.add("add");
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(list.size());
}
}

运行结果:

运行结果

线程安全的集合:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class ThreadSafe {
public static void main(String[] args) throws InterruptedException {
List<String> list = new CopyOnWriteArrayList<>();
Thread thread1 =new Thread(()->{
for (int i = 0; i < 1000; i++) {
list.add("add");
}
});
Thread thread2 = new Thread(()->{
for (int i = 0; i < 1000; i++) {
list.add("add");
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(list.size());
}
}

运行结果:

运行结果

3 使用Collections包装成线程安全

  • 包装列表list

    1
    List<String> list = Collections.synchronizedList(new ArrayList<>());
  • 包装集合set

    1
    Set<String> set = Collections.synchronizedSet(new HashSet<>());
  • 包装字典map

    1
    Map<String, String> map = Collections.synchronizedMap(new HashMap<>());

参考文献

https://blog.csdn.net/lixiaobuaa/article/details/79689338

写在最后

欢迎大家关注鄙人的公众号【麦田里的守望者zhg】,让我们一起成长,谢谢。
微信公众号