jvm组成
1.类加载器:负责将java的.class文件转化为字节码文件,并加载到运行数据区的方法区
2.运行时数据区: jvm的内存
运行数据区的组成:
堆:存储实例化对象 伊甸园:s0,s1 8:1:1 老年代:新生代 新生代->老年代 条件:15次、大对象、动态担保机制
方法区:存储类信息,常量,静态变量,jdk8之后移动至元空间
虚拟机栈:线程独有,存储方法调用,局部常量,返回信息,由一个个的栈帧组成,(一次方法调用产生一个栈帧),只有一个活动栈帧
本地方法栈:处理本地方法的调用
程序计数器:记录当前线程执行的字节码位置
3.执行引擎:负责执行字节码文件
解释器,逐行解释执行字节码文件
及时解释器:配将频繁调用的的代码前端转化为本地机器码,提高效率
垃圾回收gc,回收堆中不使用的对象实例,释放内存
4.本地借口,
通过底层调用c或者c++的方法,实现与操作系统的交互
HashMap
数据结构:
1.7是数组+链表
1.8是数组+链表/红黑树
树化的时机:数组长度大于64且链表长度大于8
扩容机制:
扩容因子是0.75是根据泊松分布验证的合理值,
扩容因子:过大导致冲突上升,过小导致空间利用率过低
扩容为原来的两倍
数组长度要数组容量必须是2的幂次方原因:
HashMap 要求容量是 2 的幂次方,最终目的是用高效的位运算代替取模运算,同时保证元素在数组中分布更均匀,从而提升查询、插入、删除的效率。
执行流程:
put的执行流程:
首先把key进行两次hash计算得到hashcode,两次hash运算主要是为了减少hash碰撞,以及其分布的更均匀
再通过与数组长度的取模运算,得到要存储的数组下标
通过数组下表查找,如果对应位置为空则key-value的node节点存储进去,否则进行相同key的链表上的查找,如果key相同则替换value,不存在则存储在链表的末端,同时判断是否达到树化的时机,是否进行树化
CourrentHashMap的区别?
- 1.7:分段锁,16个Segement对象
- 1.8:CAS+synchronized
- 低冲突用CAS
- 高冲突使用synchronized
- monitor
- 线程id
- 计数器
分布式锁
redission
zookeeper
文件夹的唯一性
etcd3
可重入锁
synchronized
reetrantLock