【每天10问】002 后端知识点 2022.02.16 周三
每天10问: 是一个系列,不代表一定是10问,可能只有3问,主要是 记录当天自己的 技术思考和收获等
- 问题01:LinkedHashMap的底层也还是 数组吗? 普通的 HashMap有什么区别?
答: 是 数组+ 双向链表 (树化后是 红黑树),普通的 HashMap是 数组+单向链表, 具体可以查看 https://blog.csdn.net/weixin_30988079/article/details/112375182 ===={知识点} 1)【知识点 01】LinkedHashMap是HashMap的一个子类,底层实现基本上和HashMap一样,只是在原来的单链表的基础上改成了双向链表,这样做的目的是为了让它能够实现插入数据的排序。也就是说如果遍历整个LinkedHashMap时,是会按照插入数据的顺序来遍历数据的。 2)【知识点 02】: Map.Entry (以 HashMap这个具体实现为例)是 HashMap的静态内部类 Map.Entry
2.问题02【todo】:LinkedHashMap中 其中的一个构造方法中的 accessOrder字段传递 true时,每次get()操作都会把get到的那个元素的顺序放到最后
这样做的意义或者作用是什么呢?
TODO --待解答
3.问题02:Java的 volatile的底层原理和使用的方法是怎样的?
答:1)volatile的特点是: ① 保证了可见性 ② 不支持原子性 ③禁止指令重排,具体参考:https://blog.csdn.net/u012723673/article/details/80682208?utm_source=app&app_version=5.0.0
【原理】:在JVM底层volatile是采用“内存屏障”来实现的。加入volatile关键字时,会多出一个lock前缀指令,这个lock的前缀指令就相当于是 内存屏障。提供的3种功能,正好是 对应 禁止指令重排 和 变量的各线程的可见性。
4.问题04:单例模式的双重锁为什么要加volatile
public class TestInstance{
private volatile static TestInstance instance;
public static TestInstance getInstance(){ //1
if(instance == null){ //2
synchronized(TestInstance.class){ //3
if(instance == null){ //4
instance = new TestInstance(); //5
}
}
}
return instance; //6
}
====
需要volatile关键字的原因是,在并发情况下,如果没有volatile关键字,在第5行会出现问题。instance = new TestInstance();可以分解为3行伪代码
a. memory = allocate() //分配内存
b. ctorInstanc(memory) //初始化对象
c. instance = memory //设置instance指向刚分配的地址
上面的代码在编译运行时,可能会出现重排序从a-b-c排序为a-c-b。在多线程的情况下会出现以下问题。当线程A在执行第5行代码时,B线程进来执行到第2行代码。假设此时A执行的过程中发生了指令重排序,即先执行了a和c,没有执行b。那么由于A线程执行了c导致instance指向了一段地址,所以B线程判断instance不为null,会直接跳到第6行并返回一个未初始化的对象。
5.问题05: Java中引用reference具体指什么?
https://cloud.tencent.com/developer/article/1657759
答: 1) 知识点 01: java中有值类型也有引用类型,引用类型一般是针对于java中对象来说的 2) 知识点 02: java为引用类型专门定义了一个类叫做Reference。Reference是跟java垃圾回收机制息息相关的类,通过探讨Reference的实现可以更加深入的理解java的垃圾回收是怎么工作的。 3)知识点03:java中的四种引用类型分别是:强引用,软引用,弱引用和虚引用。 问题01: 引用reference中的 ReferenceQueue 具体指什么,有什么作用? 答: 初步理解: 比如 软引用 SoftReference的 构造方法 public SoftReference(T referent, ReferenceQueue<? super T> q) 第二个参数叫做ReferenceQueue,是用来存储封装的待回收Reference对象的,ReferenceQueue中的对象是由Reference类中的ReferenceHandler内部类进行处理的。
4) 知识点 04:
- Reference类是所有引用类的父类
- Reference中可以在创建时注册引用队列
- Reference有四种状态,如果创建时没有注册引用队列,则只有两种状态
- 可以通过get方法获取内部的对象,但如果对象已经被回收了,则会返回null
在讲这三个Queue/List之前,我们先讲一下Reference的四个状态:
其完整生命周期
对于带ReferenceQueue的Reference,GC会把要回收对象的Reference放到ReferenceQueue中,后续该Reference需要程序员自己处理(调用poll方法)。
不带ReferenceQueue的Reference,由GC自己处理,待回收的对象其Reference状态会变成Inactive。
创建好了Reference,就进入active状态。
active状态下,如果引用对象的可到达状态发送变化就会转变成Inactive或Pending状态。
Inactive状态很好理解,到达Inactive状态的Reference状态不能被改变,会等待GC回收。
Pending状态代表等待入Queue,Reference内部有个ReferenceHandler,会调用enqueue方法,将Pending对象入到Queue中。
入Queue的对象,其状态就变成了Enqueued。
Enqueued状态的对象,如果调用poll方法从ReferenceQueue拿出,则该Reference的状态就变成了Inactive,等待GC的回收。
这就是Reference的一个完整的生命周期。
WeakHashMap
最后讲一下WeakHashMap,WeakHashMap跟WeakReference有点类似,在WeakHashMap如果key不再被使用,被赋值为null的时候,该key对应的Entry会自动从WeakHashMap中删除。
- 作者:天行健·自强不息
- 出处:http://www.cnblogs.com/aiweixiao/
- 本文版权归作者和博客园共有,欢迎转载,如需联系 sishuinianhua369#126.com
如果您觉得本文对您的学习有所帮助,可通过微信或者支付宝 来打赏博主,增加博主的写作动力
微信支付 支付宝支付