文章目录
- 底层实现
- 构造方法默认的三个参数
- 什么是Unsafe类?它有什么作用?
- 为什么CurrentHashMap 调用Unsafe方法不会报错?我们自己创建的对象调用会报错?
- CurrentHashMap的key,value可以为null吗?
- CurrentHashMap如何计算size?
- 总结流程图
- PUT:
- GET:
底层实现
- 数组+链表+Segment分段锁
构造方法默认的三个参数
-
DEFAULT_INITIAL_CAPACITY=16; //默认的初始化容量,表示每个segment下的每个默认数组大小
-
DEFAULT_LOAD_FACTOR= 0.75f; // 负载因子
-
DEFAULT_CONCURRENCY_LEVEL=16; //并发级别,默认16,表示segment数组大小。
-
构造方法总结:ConcurrentHashMap中保存了一个默认长度为16的Segment[]数组,每个Segment数组中保存了一个默认长度为2的HashEntry[]数组,我们添加元素,是存入对应的Segment数组中的HashEntry[]数组中。
什么是Unsafe类?它有什么作用?
- Unsafe类是在sun.misc包下,不属于Java标准。很多Java的基础类库,包括一些被广泛使用的高性能开发库都是基于Unsafe类开发的,比如Netty、Hadoop、Kafka等。
- 使用Unsafe可用来直接访问系统内存资源并进行自主管理,Unsafe类在提升Java运行效率,增强Java语言底层操作能力方面起了很大的作用。
- Unsafe提供了一些低层次操作,如直接内存访问、线程调度等。
- 官方并不建议使用Unsafe。
为什么CurrentHashMap 调用Unsafe方法不会报错?我们自己创建的对象调用会报错?
-
因为我们自己创建的对象使用的类加载器是ApplicationClassLoader,当调用class.getClassLoader()方法后返回不为null,所以会直接抛出异常,而CurrentHashMap使用的类加载器是BootstrapClassLoader,调用class.getClassLoader()后返回为null,所以会直接返回对象。
-
具体源码如下:
private Unsafe() {
}
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass(2);
if (var0.getClassLoader() != null) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
CurrentHashMap的key,value可以为null吗?
- 都不可以,会报错。
CurrentHashMap如何计算size?
- 遍历每个segment,先得到总数,然后得到修改的次数,然后修改次数和上一次修改次数对比,如果有变化,则代表被修改了,则重新进行遍历,并且次数+1。如果遍历次数超过阈值,则对每一个segment上锁,然后遍历。