List集合:
在main方法中造10个线程,每个线程对list集合进行添加和输出操作。
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName() + "线程, " + list);
},String.valueOf(i)).start();
}
输出结果:
发现会报异常:ConcurrentModificationException,这个异常时多线程读写异常。
然后我们使用方法将list集合变成线程安全的:
方法一:
使用Collections工具类:
jdk8.0文档:
代码演示:
ArrayList<String> list1 = new ArrayList<>();
List<String> list = Collections.synchronizedList(list1);
输出结果:
方式二:
使用java.util.concurrent包下的CopyonWriteArrayList:
CopyOnWriteArrayList list = new CopyOnWriteArrayList();
输出:
set及map集合, 可以有三种解决方式: 方式一:使用古老实现类:Vector或者Hashtable
演示代码:不安全:
//Set集合:
HashSet<String> set = new HashSet<>();
for (int i = 0; i < 30; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName() + "线程, " + set);
},String.valueOf(i)).start();
}
方式一:使用古老实现类Vector:
Vector<String> vector = new Vector<>();
输出:
方式二:使用Collections集合类:
Set<String> set = Collections.synchronizedSet(set1);
输出:
方式三:使用CopyOnWriteArraySet
CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
Map集合:
方式一:使用古老实现类:Hashtable
Hashtable<String, String> table= new Hashtable<>();
方式二:使用Collections工具类:
Map<String, String> map = Collections.synchronizedMap(map1);
方式三:使用ConcurrentHashMap
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
对于上面这些类,一般推荐使用juc包下的并发实现类,第一:古老实现类Vector,Hashtable时jdk1.0时的,底层都是使用了synchronized来解决并发,效率较低。 第二:使用Collections工具类,是从jdk1.2版本开始的,实际上底层还是使用的synchronized来解决,效率低。 使用java.util.concurrent包下的CopyOnWriteArryList类等,它实际上时复制读写,不是全区段加锁,是分段锁,性能较好。
整体演示代码:
public class ThreadDemo4 {
public static void main(String[] args) {
//List集合
//方式一:使用Collections工具类:
// ArrayList<String> list1 = new ArrayList<>();
// List<String> list = Collections.synchronizedList(list1);
//方式二:使用juc包下的
// CopyOnWriteArrayList list = new CopyOnWriteArrayList();
//
// for (int i = 0; i < 10; i++) {
// new Thread(()->{
// list.add(UUID.randomUUID().toString().substring(0,5));
// System.out.println(Thread.currentThread().getName() + "线程, " + list);
// },String.valueOf(i)).start();
// }
//Set集合:
HashSet<String> set1 = new HashSet<>();
//方式一:使用古老实现类:Vector
// Vector<String> vector = new Vector<>();
//方式二:使用Collections集合类
// Set<String> set = Collections.synchronizedSet(set1);
//方式三:使用CopyOnWriteArraySet
// CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
// for (int i = 0; i < 30; i++) {
// new Thread(()->{
// set.add(UUID.randomUUID().toString().substring(0,5));
// System.out.println(Thread.currentThread().getName() + "线程, " + set);
// },String.valueOf(i)).start();
// }
//Map集合
HashMap<String, String> map1 = new HashMap<>();
//方式一:使用古老实现类Hashtable
// Hashtable<String, String> table = new Hashtable<>();
//方式二:使用Collections集合类
// Map<String, String> map = Collections.synchronizedMap(map1);
//方式三:使用ConcurrentHashMap
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
for (int i = 0; i < 30; i++) {
String key = String.valueOf(i);
new Thread(()->{
map.put(key,UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName() + "线程, " + map);
},String.valueOf(i)).start();
}
}
}