
ThreadlocalMap 中key是 WeakReference类型,能讲讲Java中有几种类似的引用,什么区别吗?
- 强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它,当内存空间不足时,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
- 如果一个对象只具有软引用,则内存空间充足时,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。
- 弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描内存区域时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
- 虚引用顾名思义,就是形同虚设。与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
那你能讲讲为什么ThreadlocalMap 中key 设计成 WeakReference(弱引用)类型吗?
为了尽最大努力避免内存泄漏。请看上图
privatestaticfinalThreadLocal<UserInfo>userInfoThreadLocal=newThreadLocal<>();
userInfoThreadLocal.set(userInfo);
这里的引用关系是userInfoThreadLocal 引用了ThreadLocal对象,这是个强引用,ThreadLocal对象同时也被ThreadlocalMap的key引用,这是个WeakReference引用,我们前面说GC要回收ThreadLocal对象的前提是它只被WeakReference引用,没有任何强引用。
为了方便大家理解弱引用,我写了段Demo程序
public static void main(String[] args) {
Object angela = new Object();
//弱引用
WeakReference<Object> weakReference = new WeakReference<>(angela);
//angela和弱引用指向同一个对象
System.out.println(angela);//java.lang.Object@4550017c
System.out.println(weakReference.get());//java.lang.Object@4550017c
//将强引用angela置为null,这个对象就只剩下弱引用了,内存够用,弱引用也会被回收
angela = null;
System.gc();//内存够用不会自动gc,手动唤醒gc
System.out.println(angela);//null
System.out.println(weakReference.get());//null
}
可以看到一旦一个对象只被弱引用引用,GC的时候就会回收这个对象。
所以只要ThreadLocal对象如果还被 userInfoThreadLocal(强引用) 引用者,GC是不会回收被WeakReference引用的对象的。
,















