ArrayList线程不安全
import 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线程不安全
import 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线程不安全
import 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();
}
}
}