ArrayList底层原理、线程安全及其相关集合(面试常问)
一、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底层原理、线程安全及其相关集合(面试常问)的更多相关文章
- 深入浅出分析MySQL MyISAM与INNODB索引原理、优缺点、主程面试常问问题详解
本文浅显的分析了MySQL索引的原理及针对主程面试的一些问题,对各种资料进行了分析总结,分享给大家,希望祝大家早上走上属于自己的"成金之路". 学习知识最好的方式是带着问题去研究所 ...
- ArrayList底层原理
ArrayList底层采用数组实现,访问特别快,它可以根据索引下标快速找到元素.但添加插入删除等写操作效率低,因为涉及到内存数据复制转移. ArrayList对象初始化时,无参数构造器默认容量为10, ...
- 从Redis分布式缓存实战入手到底层原理分析、面面俱到覆盖大厂面试考点
概述 官方说明 Redis官网 https://redis.io/ 最新版本6.2.6 Redis中文官网 http://www.redis.cn/ 不过中文官网的同步更新维护相对要滞后不少时间,但对 ...
- JDK集合面试20问
1. HashMap的内部实现原理是什么? HashMap内部实现原理是数组+链表,通过散列算法将key值散列到数组中,如果到相同的位置,则通过拉链法解决散列冲突.在JDK8中新增了红黑树结构,当Ha ...
- 面试常问的ArrayQueue底层实现
public class ArrayQueue<T> extends AbstractList<T>{ //定义必要的属性,容量.数组.头指针.尾指针 private int ...
- 深入理解List集合框架底层原理的实现
前言: 此篇文章讲解ArrayList和LinkedList底层实现原理.for和foreach遍历集合哪个效率会更高一些! 讲讲什么是集合框架?集合框架是为表示和操作集合而规定的一种统一的标准的体系 ...
- Java8线程池ThreadPoolExecutor底层原理及其源码解析
小侃一下 日常开发中, 或许不会直接new线程或线程池, 但这些线程相关的基础或思想是非常重要的, 参考林迪效应; 就算没有直接用到, 可能间接也用到了类似的思想或原理, 例如tomcat, jett ...
- ArrayList 从源码角度剖析底层原理
本篇文章已放到 Github github.com/sh-blog 仓库中,里面对我写的所有文章都做了分类,更加方便阅读.同时也会发布一些职位信息,持续更新中,欢迎 Star 对于 ArrayList ...
- 4.Java集合-ArrayList实现原理及源码分析
一.ArrayList概述: ArrayList 是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存 ArrayList不是线程安全的,只能用在单线程的情况 ...
- 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法
==学习目标== 1.能够了解红黑树 2.能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构) 3.能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历) 4.能够掌 ...
随机推荐
- 2021-02-07:给定两棵二叉树的头节点head1和head2,如何判断head1中是否有某个子树的结构和head2完全一样?
福哥答案2021-02-07: 对head1和head2序列化为str1和str2.然后用kmp算法去判断str2是否是str1的子串.如果是,head2是子树:如果不是,head2不是子树. 代码用 ...
- AcWing 1022. 宠物小精灵之收服
宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事. 一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵. 小智也想收服其中的一些小精灵. 然而,野生的小精灵并不那么容易被收服. ...
- Kali系统 连接 Xshell
1> 进入kali系统,修改ssh配置文件:vi /etc/ssh/sshd_config 2> 将PermitRootLogin without-password修改为:PermitRo ...
- 在C++中,传值还是传引用?
情况一:需要修改原对象 需要修改原对象的情况,必须要传引用.这种情况没什么要说的. 情况二:不需要修改原对象 对于内置类型(整数.浮点数.字符类型等),传值效率更高.主要有三点原因: 内存开销更小.由 ...
- AI 协助办公 |记一次用 GPT-4 写一个消息同步 App
GPT-4 最近风头正劲,作为 NebulaGraph 的研发人员的我自然是跟进新技术步伐.恰好,现在有一个将 Slack channel 消息同步到其他 IM 的需求,看看 GPT-4 能不能帮我完 ...
- Vue3从入门到精通(二)
vue3 侦听器 在Vue3中,侦听器的使用方式与Vue2相同,可以使用watch选项或$watch方法来创建侦听器.不同之处在于,Vue3中取消了immediate选项,同时提供了新的选项和API. ...
- 了解基于模型的元学习:Learning to Learn优化策略和Meta-Learner LSTM
摘要:本文主要为大家讲解基于模型的元学习中的Learning to Learn优化策略和Meta-Learner LSTM. 本文分享自华为云社区<深度学习应用篇-元学习[16]:基于模型的元学 ...
- @Retention元注解的使用
@Retention注解标记其他的注解用于指明标记的注解保留策略:先看Java SE 8中@Target是如何声明的: package java.lang.annotation; public enu ...
- 4. JDK相关设置
恐惧是本能,行动是信仰(在此感谢尚硅谷宋红康老师的教程) 1. 项目的 JDK 设置 File-->Project Structure...-->Platform Settings --& ...
- Linux系统运维之FastDFS集群部署
一.简介 FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.FastDFS服务端有两个 ...