首先是我们的ArrayList:

这次我们讲解的是集合的不安全,首先我们都知道ArrayList吧!

List<String> list=new ArrayList<>();

首先我们拓展几个知识点,ArrayList底层是Object类型的数组,jdk7之前初始容量是10。

jdk8之后是空引用,到add之后会变成10,类似于懒加载的机制,其扩容的方式是每次扩容为之前的一半,比如10会扩容成15,15扩容成22,扩容用到的方法时Arrays的copyof方法,OK,接下来后进入主题。

我们通过Lambda表达式来生成几个线程

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

之后会报异常:
java.util.ConcurrentModificationException 并发修改异常
导致原因:多线程并发争抢统一资源(这里指list实例),且没加锁
那么我们有什么解决办法呢??

方法一:Vector

List<String> list = new Vector<>();

Vector集合,底层给add方法加了synchronized(重锁),同一时间段只有一个个线程,效率低,所以这就是为什么Vector集合安全效率低的原因

方法二:Collections.synchronizedList

Collections.synchronizedList(new ArrayList<>());

这是Connections的静态方法,传入一个ArrayList。

方法三:CopyOnWriteArrayList

List<String> list = new CopyOnWriteArrayList<>();

jdk1.5之后,这个JUC包当中的CopyOnWriteArrayList类,实现了List接口。

public class CopyOnWriteArrayList<E>
extends Object
implements List<E>, RandomAccess, Cloneable, Serializable

CopyOnWriteArrayList的底层:volatile Object[] array

其add()方法里面加了锁ReentrantLock:写前复制,length+1

public boolean add(E e) {
final ReentrantLock lock = this.lock; //加锁
lock.lock();
try {
Object[] elements = getArray(); //先得到老版本的集合
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}

注意:CopyOnWriteArrayList的扩容同样用的是Arrays工具类的copyof()方法,但一次扩容1

接着我们来看Set集合:

同样扩展点知识点,HashSet底层数据结构是HashMap,HashSet源码构造器是new HashMap(),

map集合添加元素,丢进去的是K-V键值对

但是set是无序的集合,set的元素添加是对一个对象进去。数量对不上啊,这不是互相矛盾么?所以接下来分析HashSet的底层实现源码:

HashSet的add方法实际上调的是map的put方法:,set添加的元素就是put()里面的key,因为set不会重复,keys也就不会重复

PRESENT实际上就是一个object常量,value并不重要

同样的步骤:

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

同样是报错:
java.util.ConcurrentModificationException
解决方案:

方法一:Collections.synchronizedSet

Set<String> set=Collections.synchronizedSet(new HashSet<>());

方法二:CopyOnWriteArraySet

 Set<String> set=new CopyOnWriteArraySet();

也是JUC的里的类,其构造器是new CopyOnWriteArraySet();

public class CopyOnWriteArraySet<E>
extends AbstractSet<E>
implements Serializable

然后就是我们的Map:

扩展知识:HashMap(无序无重复)底层是数组+链表(单向)+红黑树。

HashMap存的是node节点,node里面存K-V键值对,node里面存的是Key-Value,HashMap初始容量为16,负载因子为0.75(到16*0.75的时候扩容)。每次扩容为原值得一倍

初始容量和负载因子可以通过构造器来改。

Constructor and Description
HashMap()
构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。
HashMap(int initialCapacity)
构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。
HashMap(int initialCapacity, float loadFactor)
构造一个空的 HashMap具有指定的初始容量和负载因子。
HashMap(Map<? extends K,? extends V> m)
构造一个新的 HashMap与指定的相同的映射 Map 。

同样的操作:

 Map<String, String> map = new HashMap<>();
for (int i = 0; i < 30; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 8));
System.out.println(map);
}, String.valueOf(i)).start();
}

同样的会报错:
java.util.ConcurrentModificationException
解决办法:

 Map<String, String> map = new ConcurrentHashMap();

Java.util.concurrent包下的ConcurrentHashMap:

public class ConcurrentHashMap<K,V>
extends AbstractMap<K,V>
implements ConcurrentMap<K,V>, Serializable

这次就是本次讲解的JUC之集合不安全,希望能帮助到大家,如果有更好的建议,欢迎大家留言!

Java高并发,ArrayList、HashSet、HashMap不安全的集合类的更多相关文章

  1. Java高并发如何解决

    Java高并发如何解决 对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题,但话又说回来了,既然逃避不掉,那我们就坦然面对吧 ...

  2. 转载:Java高并发,如何解决,什么方式解决

    原文:https://www.cnblogs.com/lr393993507/p/5909804.html 对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并 ...

  3. Java高并发综合

    这篇文章是研一刚入学时写的,今天整理草稿时才被我挖出来.当时混混沌沌的面试,记下来了一些并发的面试问题,很多还没有回答.到现在也学习了不少并发的知识,回过头来看这些问题和当时整理的答案,漏洞百出又十分 ...

  4. 【转】Java高并发,如何解决,什么方式解决

    原文地址:https://www.cnblogs.com/lr393993507/p/5909804.html 对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了. ...

  5. 《实战Java高并发程序设计》读书笔记

    文章目录 第二章 Java并行程序基础 2.1 线程的基本操作 2.1.1 线程中断 2.1.2 等待(wait)和通知(notify) 2.1.3 等待线程结束(join)和谦让(yield) 2. ...

  6. java高并发系列 - 第26篇:学会使用JUC中常见的集合,常看看!

    这是java高并发系列第26篇文章. 环境:jdk1.8. 本文内容 了解JUC常见集合,学会使用 ConcurrentHashMap ConcurrentSkipListMap Concurrent ...

  7. 如何解决java高并发详细讲解

    对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题, 但话又说回来了,既然逃避不掉,那我们就坦然面对吧~今天就让我们一起来研 ...

  8. Java高并发系列——检视阅读

    Java高并发系列--检视阅读 参考 java高并发系列 liaoxuefeng Java教程 CompletableFuture AQS原理没讲,需要找资料补充. JUC中常见的集合原来没讲,比如C ...

  9. Java高并发 -- 并发扩展

    Java高并发 -- 并发扩展 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 死锁 死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象, ...

  10. Java高并发 -- 线程池

    Java高并发 -- 线程池 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 在使用线程池后,创建线程变成了从线程池里获得空闲线程,关闭线程变成了将线程归坏给线程池. ...

随机推荐

  1. Python 计算几月几号是某年的第几天

    闰年需要同时满足以下条件: 1.年份能被4整除: 2.年份若是 100 的整数倍的话需被400整除,否则是平年. #!/usr/bin/python # -*- coding: UTF-8 -*- # ...

  2. 解锁GraphRag.Net的无限可能:手把手教你集成国产模型和本地模型

    在上次的文章中,我们已经详细介绍了GraphRag的基本功能和使用方式.如果你还不熟悉,建议先阅读前面的文章 通过前两篇文章,相信你已经了解到GraphRag.Net目前只支持OpenAI规范的接口, ...

  3. 深度解读昇腾CANN小shape算子计算优化技术,进一步减少调度开销

    摘要:Host调度模式下,GE将模型中算子的执行单元划分为Host CPU执行与Device(昇腾AI处理器)执行两大类. 本文分享自华为云社区<深度解读昇腾CANN小shape算子计算优化技术 ...

  4. 使用触发器来审计表的DML、DDL操作

    最近帮客户排查某问题时,因为怀疑应用对某张配置表有变更,所以需要对这张表的所有操作进行审计. 原本Oracle对某张表的审计是非常方便的,一条命令就可以实现,也不需要费心自定义审计表. -- 启用对表 ...

  5. 为啥动态显示的名字就显示了undefined?

    看不懂了昂,记录一下,慢慢理解吧 <!DOCTYPE html> <html> <head> <meta charset="utf-8"& ...

  6. SMU 2024 spring 天梯赛1

    SMU 2024 spring 天梯赛1 7-1 种钻石 - SMU 2024 spring 天梯赛1 (pintia.cn) #include <bits/stdc++.h> #defi ...

  7. 玄机蓝队靶场_应急响应_02:apache日志分析

    日志分析这块,感觉都是对grep.awk.sort.wc.uniq,这几个命令的使用. 一:靶场 (1)直接cd到linux日志, cd /var/log 发现apache2目录, cd ./apac ...

  8. 手把手在STM32F103C8T6上构建可扩展可移植的DHT11驱动

    前言 如何驱动一个你陌生的传感器呢?别看我,也别在网上死马当活马医!你需要做的,首先是明确你的传感器的名称,在这里,我们想要使用的是DHT11温湿度传感器 可能需要的前置知识 简单的OLED驱动原理 ...

  9. Java并发编程之验证volatile指令重排-理论篇

    Java并发编程之验证volatile指令重排-理论篇 Java并发包下的类中大量使用了volatile关键字.通过之前文章介绍,大家已经知道了volatile的三大特性:共享变量可见性:不保证原子性 ...

  10. 肉夹馍(Rougamo)4.0.1 异步方法变量调试修复与IoC系列扩展

    肉夹馍(https://github.com/inversionhourglass/Rougamo),一款编译时AOP组件,无需在应用启动时进行初始化,也无需繁琐的配置:支持所有种类方法(同步和异步. ...