JUC解决多线程集合线程不安全,以及ConcurrentModificationException(并发修改异常)

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();
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值