如今稍微大点的公司面试,可能会问到ThreadLocal源码实现,不过在介绍它以前,咱们先介绍JVM中引用的概念。所谓这些概念就是我所说的基础了。引用强弱关系到内存垃圾回收时机,用好引用能够减轻内存压力。JVM引用一共分为4种,分别是强引用,软引用,弱引用和虚引用。面试
如上图:根引用list指向堆,一直向list添加512K的字节数组,程序几秒后会出现堆溢出,代码中list引用称为强引用。强引用内存一直不会被释放,直到内存溢出。数组
如上图代码:主函数中,软引用须要用SoftReference包装user对象,运行程序先配置初始化参数,-Xmx10M 设置堆空间为10m,设置user=null,user引用消失,主函数第一次调用GC时,控制台输出User对象信息,说明堆中User对象还存在,user对象并无被回收,这是由于软引用softRef指向堆中User 对象,申请内存byte[] bytes = new byte[1024*985*6];bytes 约6M,bytes引用对象会进入老年代,此时老年代会GC,此时控制台会输出null,说明此时userRef失去引用,堆中的user对象都被当成垃圾回收了。为何要设置bytes 约6M,是由于想测试一个结论:当内存不足时,GC会回收软引用。缓存
特别注意:调试时,985设置bytes引用执行堆内存的大小,须要本身调试,才可能出现上述结果。安全
如上图代码:弱引用对象须要用WeakReference包装,GC后,弱引用对象被回收。总结一句:当GC时,无论内存够不够,弱引用会被回收。咱们的ThreadLocal就是被WeakRefernece包装。微信
小结下:强引用,软引用,弱引用,虚引用的生命力是从高往低的。生命力越低越容易被回收,强引用则没法被回收,软引用比较适用于缓存的场景,软引用只有内存紧张时才会被回收,弱引用只要发生GC会被回收。ide
ThreadLocal是线程安全的,由于它能让每一个线程都拥有本身独享变量。它也可让一个线程拥有多个变量。底层使用hash表实现的数组,说白了就是一个HashMap,其中key是ThreadLocal,value就是值。使用起来很方便。函数
如上图代码:建立一个ThreadLocal,当调用set时,主线程就拥有了本身的私有变量“叫练”了,经过get就能够取出来。但这里有个问题,源码中ThreadLocal是被WeakReference包装的。为何要这么作!这样作的目的是为了节约内存,下面咱们详细了解下!学习
我问本身下面几个问题:测试
不会,当线程结束,ThreadLocal才有可能回收,注意是有可能,由于还有其余的线程引用了当前ThreadLocal。spa
防止内存泄漏,为了回收内存。
由于Entry中的value多是一个对象,而这个对象可能被其余线程引用,一旦设置Entry为WeakReference,可能致使其余线程空指针。
每次使用完ThreadLocal以后,须要调用remove方法,清除当前线程的threadLocal。
学习不是一蹴而就的,你们看若是你不去了解JVM引用,你就没法搞清楚ThreadLocal源码。好了,文章有地方还写的不清晰但愿亲们加以指正和点评,喜欢的请点赞加关注哦。点关注,不迷路,我是叫练,边叫边练,公众号【叫练】,微信号【jiaolian123abc】。