集合类不安全_List_Set_HashMap

集合类不安全

1.单线程的代码永远是安全的
并发下这些所有的集合类都有问题

List 不安全

代码案例:

package com.unsafe;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 面试官问写代码遇到什么异常?
 * 可以回答的高级点
 * 1.我遇到的是OOM 内存异常
 * 2.我遇到java.util.ConcurrentModificationException  并发修改异常!
 *
 *1.解决ArrayList 不安全方案
 *
 */
public class ListTest {


    public  static void main(String[] args) {
//        List<String> list = Arrays.asList("1", "2", "3");
//        list.forEach(System.out::println);
         //并发下ArrayList 不安全吗? 不安全
        /**
         * 解决方案:
         * 1. list 下面还有一个Vector 默认就是安全的
         * 2. List<String> list = Collections.synchronizedList(new ArrayList<>());
         * 3. List<String> list = new CopyOnWriteArrayList<>();
         */
        //ArrayList<String> list = new ArrayList<>();
        //List<String> list = new Vector<>();
        //将一个ArrayList 变得安全
        //List<String> list = Collections.synchronizedList(new ArrayList<>());
        //CopyOnWrite 写入时复制 COW  计算机程序设计领域的一种优化策略
        //多个线程调用的时候,list,读取的时候,固定的,写入的时候存在覆盖操作,写入(覆盖)
        // 在写入的时候避免覆盖,造成数据问题!


        // 读写分离 Mycat
        // 为什么不用Vector 而用 copyOnWriteArrayList?
        //Vector 用的是synchronized 效率比较低,而CopyOnWriteArrayList 用的是lock 锁
         List<String> list = new CopyOnWriteArrayList<>();

        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }
}

小狂神的学习方法推荐: 1.先会用,2,货比3家,寻找其他解决方案,3 ,分析源码

Vector 用关键字synchronized 关键字修饰,是线程安全的
在这里插入图片描述

CopyOnWriteArrayList :写入时复制
lock 锁
在这里插入图片描述

  1. 先初始化一个数组,
  2. 获取之前数组长度,
  3. 复制之前的数组并且长度加1
  4. 将add 的新增到对应数组的位置
  5. 将数组转化为List

Set 不安全

在这里插入图片描述
Collection 下面还有一个叫阻塞队列的东西BlockingQueue

package com.unsafe;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
/**
 * 同理可证:   ConcurrentModificationException 并发修改异常
 * // 工具类写法:1..通过集合类使用synchronizedSet 方法    Set<Object> objects = Collections.synchronizedSet(new HashSet<>());
 * // JUC 写法:   Set<String> set = new CopyOnWriteArraySet<>();   写入时复制
 */
public class SetTest {

    public static void main(String[] args) {
        // Set<String> set = new HashSet<>();
        //如何将set 变成线程安全的
        //1.通过结合类使用synchronizedSet 方法
        //

        // Set<Object> objects = Collections.synchronizedSet(new HashSet<>());
        Set<String> set = new CopyOnWriteArraySet<>(); //写入时复制

        for (int i = 0; i < 30; i++) {
            new Thread(() -> {
                set.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(set);
            }, String.valueOf(i)).start();
        }


    }

}

HashSet 底层是什么?
HashSet 的底层就是HashMap
在这里插入图片描述
//add 方法本质方法是map 的key 是无法重复的!而put 里面的Value Present 是不变的值

    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

	//PRESENT 是常量
   private static final Object PRESENT = new Object();//不变的值

Map 不安全
回顾hashMap 的基本操作
在这里插入图片描述
1.理解这些是什么
在这里插入图片描述

package com.unsafe;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * java.util.ConcurrentModificationException 并发修改异常
 * 如何将hashMap 编程线程安全的?
 * 1.使用工具类Collections.SynchronizedMap
 * 2.使用类ConcurrentHashMap
 *
 */
public class MapTest {


    public static void main(String[] args) {
        //map 是这样用的吗? 不是,工作中不用HashMap
        // 默认等价于什么?
        //Map<String, String> hashMap = new HashMap(16,0.75f);
        //加载因子,初始化容量
       // Map<String, String> map = new HashMap();
        //如何变成线程安全的
        // 1.使用工具类Collections :Map<Object, Object> objectObjectMap = Collections.synchronizedMap(new HashMap());
        // 2.使用ConcurrentHashMap 类 线程安全的
        //研究一下ConcurrentHashMap 原理????
         Map<String,String> map= new ConcurrentHashMap<>();

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


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值