一、ArrayList底层原理

1.特点及其原理:ArrayList底层基于数组实现,查找快,增删慢

2.ArrayList底层原理,初始化及调用add()方法添加元素:

默认初始化容量为10

第一次创建集合并在添加第一个元素时在底层创建一个默认长度为10的数组: ​

调用构造函数初始化时默认创建的是空数组

只有在调用add方法添加第一个元素时才会在底层创建默认长度为10的数组

总结:第一次创建集合并添加第一个元素时在底层创建一个默认长度为10的数组;当元素插满,会进行扩容,每次扩容到之前的1.5倍(oldCapacity + (oldCapacity >> 1,二进制右移即除二,左移乘二),如果扩容1.5倍之后容量还不够,则将所需要的最小容量minCapacity赋给数组新的容量值newCapacity;扩容之后通过数组的拷贝(使用Arrays.copyOf)来确保元素的准确性。

二、ArrayList线程安全问题

由上图add()方法可知,在ArrayList中的add方法没有做相关线程安全的处理,故ArrayList本身是线程不安全的,与之相关的线程安全的方法有:

1.Vector类

Vector和ArrayList语法相同,都继承了同一个类实现了相同的接口

Vector中的add()方法添加了synchronized关键字,故Vector类是线程安全的

但是由于Vector是直接在方法上使用synchronized锁住整个方法,并发效率低,在高并发的情况下容 易造成线程阻塞等问题。

2.使用Collections工具类

使用集合的工具类Collections提供的synchronizedList方法将线程不安全的集合类变为安全的

//将线程不安全的集合对象作为参数传入synchronizedXxx()方法中

List synchronizedList = Collections.synchronizedList(arrayList);

新new一个线程安全的SynchronizedRandomAccessList或SynchronizedList。当传入的 list 是ArrayList 时,返回 SynchronizedRandomAccessList 对象;传入 LinkedList 时,返回SynchronizedList 对象。(因为ArrayList实现了RandomAccess接口而 LinkedList 没有)

而SynchronizedRandomAccessList又继承了SynchronizedList,在调用SynchronizedRandomAccessList时构造器会调用super(list)即SynchronizedList类

可以看到SynchronizedList中的add、get、remove等方法内都加了mutex对象锁,从而实现线程安全。

与Vector比较,Vector直接锁住整个方法,而使用synchronizedList时锁住方法内部的部分代码,效率会高一点。

3.在大量并发情况下使用CopyOnWriteArrayList提高集合的效率和安全

使用Lock锁相较于Synchronized关键字更为灵活、效率更高;使用transient保证值被修改后,其它线程能够立马感知到最新值。且CopyOnWriteArrayList中只有写操作加了lock锁,而读操作(get方法)未加锁,从而提高读取效率(而synchronizedList和Vector中的get方法均加了synchronized关键字):

从 add ()方法中可以看出,CopyOnWriteArrayList 通过volatile、加锁 、 以及数组拷贝来保证了集合的线程安全。

总结:CopyOnWriteArrayList是一个读操作时无锁,写操作时使用volatile关键字、lock锁以及数组拷贝来保证线程安全的ArrayList。

三、ArrayList与相关集合的区别

1.ArrayList和LinkedList

  • ArrayList底层基于数组,LinkedList底层基于双链表

  • 广泛上来说:ArrayList适合查询,LinkedList适合插入,但是如果获取的是第一个元素,或最后一个元素,LinkedList查询也很快,因为LinkedList中有两个属性分别记录了当前链表中的头结点和尾结点。

  • ArrayList实现了RandomAccess接口,以便在随机访问列表或顺序访问列表时提供良好的性能;而LinkedList没有实现该接口。

    2.ArrayList和Vector

  • ArrayList同一时间允许多个线程进行访问,效率高、但是线程不安全,而Vector是线程安全的,但是效率低

  • ArrayList扩容是每次扩大到原来的1.5倍,Vector扩容是增加原来的两倍

  • ArrayList可使用集合工具类Collections的synchronizedList方法将线程不安全的ArrayList集合变为安全的,所以现在很少会使用到Vector

ArrayList底层原理、线程安全及其相关集合(面试常问)的更多相关文章

  1. 深入浅出分析MySQL MyISAM与INNODB索引原理、优缺点、主程面试常问问题详解

    本文浅显的分析了MySQL索引的原理及针对主程面试的一些问题,对各种资料进行了分析总结,分享给大家,希望祝大家早上走上属于自己的"成金之路". 学习知识最好的方式是带着问题去研究所 ...

  2. ArrayList底层原理

    ArrayList底层采用数组实现,访问特别快,它可以根据索引下标快速找到元素.但添加插入删除等写操作效率低,因为涉及到内存数据复制转移. ArrayList对象初始化时,无参数构造器默认容量为10, ...

  3. 从Redis分布式缓存实战入手到底层原理分析、面面俱到覆盖大厂面试考点

    概述 官方说明 Redis官网 https://redis.io/ 最新版本6.2.6 Redis中文官网 http://www.redis.cn/ 不过中文官网的同步更新维护相对要滞后不少时间,但对 ...

  4. JDK集合面试20问

    1. HashMap的内部实现原理是什么? HashMap内部实现原理是数组+链表,通过散列算法将key值散列到数组中,如果到相同的位置,则通过拉链法解决散列冲突.在JDK8中新增了红黑树结构,当Ha ...

  5. 面试常问的ArrayQueue底层实现

    public class ArrayQueue<T> extends AbstractList<T>{ //定义必要的属性,容量.数组.头指针.尾指针 private int ...

  6. 深入理解List集合框架底层原理的实现

    前言: 此篇文章讲解ArrayList和LinkedList底层实现原理.for和foreach遍历集合哪个效率会更高一些! 讲讲什么是集合框架?集合框架是为表示和操作集合而规定的一种统一的标准的体系 ...

  7. Java8线程池ThreadPoolExecutor底层原理及其源码解析

    小侃一下 日常开发中, 或许不会直接new线程或线程池, 但这些线程相关的基础或思想是非常重要的, 参考林迪效应; 就算没有直接用到, 可能间接也用到了类似的思想或原理, 例如tomcat, jett ...

  8. ArrayList 从源码角度剖析底层原理

    本篇文章已放到 Github github.com/sh-blog 仓库中,里面对我写的所有文章都做了分类,更加方便阅读.同时也会发布一些职位信息,持续更新中,欢迎 Star 对于 ArrayList ...

  9. 4.Java集合-ArrayList实现原理及源码分析

    一.ArrayList概述: ArrayList 是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存 ArrayList不是线程安全的,只能用在单线程的情况 ...

  10. 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法

    ==学习目标== 1.能够了解红黑树 2.能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构) 3.能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历) 4.能够掌 ...

随机推荐

  1. 2020-08-18:介绍下MR过程?

    福哥答案2020-08-18:[来自[MapReduce执行过程及运行原理详解] 答案](https://www.panziye.com/bigdata/625.html)MapReduce执行的4个 ...

  2. 2021-03-08:在一个数组中,任何一个前面的数a,和任何一个后面的数b,如果(a,b)是降序的,就称为逆序对。返回逆序对个数。

    2021-03-08:在一个数组中,任何一个前面的数a,和任何一个后面的数b,如果(a,b)是降序的,就称为逆序对.返回逆序对个数. 福哥答案2021-03-08: 1.归并排序,从右往左,相等拷右. ...

  3. C++中的字符串编码处理

    今天由于在项目中用到一些与C++混合开发的东西 ,需要通过socket与C++那边交换数据,没啥特别的,字节码而已,两边确定一种编码规则就行了.我们确定的UTF-8.关于C++的 这种又是宽字节 又是 ...

  4. Selenium - 元素操作(5) - iframe切换

    Selenium - 元素操作 iframe切换 很多时候定位元素时候总是提示元素定位不到的问题,明明元素就在那里,这个时候就要关注你所 定位的元素是否在frame和iframe里面: frame标签 ...

  5. AIGC持续火爆大模型争相推出,庞大市场造就算力供应模式演变

    本图由AI生成 黄仁勋说的AI发展迎来iPhone时刻,对NVIDIA有什么影响? 文/王吉伟 近期的AIGC领域仍旧火爆异常. 但火的不只是AIGC应用,还有巨头之间的AI竞赛,以及接连不断上新的A ...

  6. windows下搭建docker容器环境

    下载Docker Desktop https://www.docker.com/ 安装Docker Desktop(软件默认安装c盘,若要安装到其他盘,在安装之前创建软连接再进行安装) 在自定义磁盘中 ...

  7. idea过期解决

    用作用作发现过期了,苦恼,好办直接 搞个code 就行 MNQ043JMTU-eyJsaWNlbnNlSWQiOiJNTlEwNDNKTVRVIiwibGljZW5zZWVOYW1lIjoiR1VPI ...

  8. windows笔记本极致省电指南

    用到了三个软件:parkcontrol,process lasso,quickCPU parkcontrol -调整CPU的运行核心和频率,可以设置离电的时候关闭一些CPU核心数,以达到省电的目的 插 ...

  9. 【VS Code 与 Qt6】运用事件过滤器批量操作子级组件

    如果某个派生自 QObject 的类重写 eventFilter 方法,那它就成了事件过滤器(Event Filter).该方法的声明如下: virtual bool eventFilter(QObj ...

  10. k8s+log-pilot日志收集

    github 地址:https://github.com/AliyunContainerService/log-pilot 介绍 log-pilot是一个很棒的 docker 日志工具.可以从dock ...