5- 集合类安全
5.1 List集合
5.1.1 单线程
package cn.guardwhy.List01;
import java.util.Arrays;
import java.util.List;
/*
单线程安全
*/
public class ListTest01 {
public static void main(String[] args) {
List<String> list = Arrays.asList("kobe", "curry", "james");
list.forEach(System.out::println);
}
}
5.1.2 多线程
package cn.guardwhy.List01;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/*
并发修改异常:java.util.ConcurrentModificationException
*/
public class ListTest02 {
public static void main(String[] args) {
// 1.创建list集合
List<String> list = new ArrayList<>();
// 2.多线程
for (int i = 0; i <= 100; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,10));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
执行结果
5.1.3 解决线程不安全
CopyOnWriteArrayList
代码示例
package cn.guardwhy.List01;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/*
并发下Arraylist是不安全的
*/
public class ListTest03 {
public static void main(String[] args) {
/*
* 解决方案:
* 1. List<String> list = new Vector<>();
* 2. List<String> list = Collections.synchronizedList(new ArrayList<>());
* 3. List<String> list = new CopyOnWriteArrayList<>();
*/
// 1.创建list集合
// CopyOnWrite 写入时复制
List<String> list = new CopyOnWriteArrayList<>();
// 2.多线程
for (int i = 0; i <= 100; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,10));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
写入时复制(CopyOnWrite)思想
写入时复制(简称COW)思想是计算机程序设计领域中的一种优化策略。此做法主要的优点是如果调用者没有修改资源,就不会有副本private copy)被创建,因此多个调用者只是读取操作时可以共享同一份资源。读写分离,写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array。
CopyOnWriteArrayList性能比Vector好
Vector是增删改查方法都加了synchronized,保证同步,但是每个方法执行的时候都要去获得锁,性能就会大大下降,而CopyOnWriteArrayList 只是在增删改上加锁,但是读不加锁,在读方面的性能就好于Vector,CopyOnWriteArrayList支持读多写少的并发情况。
5.2 Set集合
5.2.1 多线程
package cn.guardwhy.List01;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
// java.util.ConcurrentModificationException
public class SetTest01 {
public static void main(String[] args) {
// 1.创建Set集合
Set<String> set = new HashSet<>();
// 2.多线程
for (int i = 0; i <= 100; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,10));
System.out.println(set);
},String.valueOf(i)).start();
}
}
}
5.2.2 解决线程不安全
CopyOnWriteArraySet
代码示例
package cn.guardwhy.List01;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
public class SetTest01 {
public static void main(String[] args) {
/*
解决方案:
1. Set<String> set = Collections.synchronizedSet(new HashSet<>());
2. Set<String> set = new CopyOnWriteArraySet<>();
*/
// 1.创建Set集合
Set<String> set = new CopyOnWriteArraySet<>();
// 2.多线程
for (int i = 0; i <= 100; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,10));
System.out.println(set);
},String.valueOf(i)).start();
}
}
}
hashset底层就是hashMap
add方法 就是map的put方法
5.3 Map集合
5.3.1 源码分析
hashMap底层是数组+链表+红黑树
Map<String,String> map = new HashMap<>();
// 等价于
Map<String,String> map = new HashMap<>(16,0.75);

5.3.2 多线程
package cn.guardwhy.List01;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/*
并发修改异常:java.util.ConcurrentModificationException
*/
public class MapTest01 {
public static void main(String[] args) {
// 1.创建Map集合对象
Map<String, String> map = new HashMap<>();
// 2.多线程
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();
}
}
}
执行结果
扫描二维码关注公众号,回复:
12662128 查看本文章

5.3.2 解决线程不安全
ConcurrentHashMap
代码示例
package cn.guardwhy.List01;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/*
并发修改异常:java.util.ConcurrentModificationException
*/
public class MapTest01 {
public static void main(String[] args) {
Map<String, String> map = new ConcurrentHashMap<>();
// 2.多线程
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();
}
}
}