Array List原理
ArrayList初始化无参构造时构造的长度为零有参构造时构造的长度为传入的参数值的长度
调用add()方法:
长度为零时第一次添加扩容为10(0~9)超过10个之后的每一次扩容的容量为上一次的1.5倍(即15)扩容的底层不是用乘实现的105倍而是用移位(15>>1)来实现的(15>>1=22)
调用addAll()方法,当第一次增加集合中的元素少于10个时扩容的容量为10,当大于10时则扩容的容量为两者之间大的容量。
ArrayList除了在头部增删比LinkedList慢意外其他都快于LinkedList,所以在实际应用中一般使用ArrayList。
CPU读内存的速度慢运算的速度快严重失衡,解决这个问题我们需要加一个CPU缓存把需要读取的数据预先读到CPU缓存,之后需要的时候CPU再直接从缓存中拿
ArrayList vsLinkedList 局部性原理
当你读取一组数据中的其中一个时,其相邻数据也很有可能会用到就一次性都读入。ArrayList因为是连续存储可以很好的利用局部性原理,而LinkedList中的数据在内存中不是相邻的一起读入时很有可能读到无关数据
HashMap
在删除树节点的这个过程是先判断再删除,判断的三个节点中有一个为空则进行拆分然后再进行删除。
小tip在进行索引计算的时候hash值取模比如hash值为a,table的容量为b,a%b可以换成a&(b-1)代入数字97%16=1 97&(16-1)=1 通过a&(b-1)取模的运算效率会更快。不过用这种方式的前提是b必须是2的次幂
put()方法在添加元素时达到阈值是先把节点加到旧数组中然后再足一把旧数组中的每个元素迁移到新建好的已扩容的数组中去
单例设计模式
1.懒汉式
几种破环单例模式的解决方案
反射直接调用私有的方法破坏单例
序列化后反序列化破坏单例
Unsafe 破坏单例这种目前没有解决方法
解决方法
枚举饿汉式
懒汉式
存在线程安全问题需要给创建对象的方法加锁
懒汉式单例 - DCL 双检锁
volatile作用是给构造方法加一层屏障多线程情况下防止构造方法跑到赋值后面
并发
Java线程分为六种状态
五种状态
线程池的核心参数
sleep vs wait lock vs synchronized
volatite 能否保证线程安全
可见性问题
下图说法是错误的有些小问题
JIT 为Java的即时编译器是JVM的一个重要组成部分他的主要责任是负责代码的优化,任何一个Java代码最终都是翻译成字节码指令,但是这个字节码指令还不能直接交给CPU进行执行,还有一个解释器的组件这个解释器会把Java的字节码指令逐行翻译成机器码机器码再交给CPU,这样CPU才能认识然后执行。每行字节码都要做翻译的动作变成机器码效率就比较低这时JIT就来对一些热点的字节码进行优化(热点字节码即为频繁调用的方法包括反复执行的循环)
下图为正确原因
volatite 解决指令重排序问题
悲观锁 vs 乐观锁
HashTable vs ConcurrentHashMap
谈谈对ThreadLocal的理解
Java虚拟机
jvm的内存结构
JVM内存参数
JVM垃圾回收算法
说说GC和分代回收算法
三色标记与并发漏标问题
项目什么情况下会内存溢出,怎么解决的
类加载过程、双亲委派机制
一个错误的面试解答
对象引用类型分为哪几类?
finalize的理解
ApplicationContext refresh