前言在ThreadLocal源码中,嵌套类ThreadLocalMap中的Entry继承了WeakReferenc。Java中提供这四种引用类型的目的主要有两个:第一个是让程序员通过代码来确定某些对象的生命周期;第二个是为了便于JVM进行垃圾收集。强引用(StrongReference)强引用是最常用的引用。如果一个对象有强引用,垃圾收集器将永远不会收集它。如下:Objecto=newObject();//强引用当内存空间不足时,Java虚拟机宁愿抛出OutOfMemoryError错误,导致程序异常终止,也不会通过回收对象来解决内存不足的问题随意使用强引用。如果不使用,应该通过以下方式弱化引用,如下:o=null;//帮助垃圾回收器回收这个对象显式设置o为null,或者超出对象的生命周期范围,gc认为表示该对象无效有引用,此时可以回收该对象。什么时候收集取决于gc的算法。例如:publicvoidtest(){Objecto=newObject();//省略其他操作}一个方法内部有一个强引用,这个引用保存在栈中,真正的引用内容(Object)保存在堆中.当方法运行结束后,会退出方法栈,引用内容的引用不存在,Object会被回收。但是如果这个o是一个全局变量,那么在这个对象不用的时候就需要赋值null,因为强引用是不会被垃圾回收的。强引用在实践中非常重要。拿ArrayList的实现源码来说:privatetransientObject[]elementData;publicvoidclear(){modCount++;//让gcdoitsworkfor(inti=0;isoftRef=newSoftReference(str);//软引用当内存不足时,相当于:if(JVM.Insufficientmemory()){str=null;//转换为软引用System.gc();//垃圾收集器回收}软引用在实际中有重要的应用,比如浏览器的后退按钮。当你按下返回时,返回时显示的网页内容是重新请求还是从缓存中取出?这取决于具体的实施策略。如果网页在浏览结束时被回收,当您按返回查看以前浏览过的页面时,您需要重建它。如果将浏览过的网页存放在内存中,会造成大量的内存浪费,甚至会造成内存溢出。随时可以使用软引用browserprev=newBrowser();//获取页面浏览SoftReferencesr=newSoftReference(prev);//浏览后设置为软引用if(sr.get()!=null){rev=(Browser)sr.get();//还没有被回收器回收,直接获取}else{prev=newBrowser();//因为内存紧张,回收软引用的对象sr=newSoftReference(prev);//Rebuild}这样很好的解决了实际问题。软引用可以与引用队列(ReferenceQueue)结合使用。如果软引用引用的对象被垃圾回收器回收,Java虚拟机会将软引用添加到与其关联的引用队列中。弱引用(WeakReference)弱引用也用来描述非本质对象。JVM在进行垃圾回收时,无论内存是否充足,弱引用关联的对象都会被回收。在java中,它由java.lang.ref.WeakReference类表示。弱引用和软引用的区别在于只有弱引用的对象生命周期更短。在垃圾回收线程扫描其管辖内存区域的过程中,一旦发现只有弱引用的对象,无论当前内存空间是否足够,都会回收其内存。然而,由于垃圾收集器是一个非常低优先级的线程,只有弱引用的对象可能无法快速找到。Stringstr=newString("abc");WeakReferenceabcWeakRef=newWeakReference(str);str=null;垃圾回收器扫描回收时,相当于:str=null;System.gc();如果这个对象是偶尔用到的,你想在用到的时候随时获取,但是你不想影响到这个对象的垃圾回收,那么就应该使用WeakReference来记住这个对象。下面的代码会让str再次成为强引用:Stringabc=abcWeakRef.get();弱引用可以与引用队列(ReferenceQueue)结合使用。如果弱引用引用的对象被垃圾回收,Java虚拟机会将这个弱引用添加到与其关联的引用队列中。当你想引用一个对象,但是这个对象有自己的生命周期,而你又不想干预这个对象的生命周期,那么就使用弱引用。该引用不会对对象垃圾回收判断产生任何额外影响publicclassReferenceTest{privatestaticReferenceQueuerq=newReferenceQueue();publicstaticvoidcheckQueue(){Referenceref=null;while((ref=rq.poll())!=null){if(ref!=null){System.out.println("Inqueue:"+((NiuhBigWeakReference)(ref)).id);}}}publicstaticvoidmain(Stringargs[]){intsize=3;LinkedList>weakList=newLinkedList>();for(inti=0;i{publicStringid;publicNiuhBigWeakReference(NiuhBigbig,ReferenceQueuerq){super(big,rq);this.id=big.id;}protectedvoidfinalize(){System.out.println("FinalizingNiuhBigWeakReference"+id);}}final的输出结果为:Justcreatedweak:com.niuh.NiuhBigWeakReference@3d075dc0Justcreatedweak:com.niuh.NiuhBigWeakReference@214c265eJustcreatedweak:com.niuh.NiuhBigWeakReference@448139f0FinalizingNiuhBigWeak2FinalizingNiuhBigWeak1FinalizingNiuhBigWeak0Inqueue:Weak2Inqueue:Weak1Inqueue:Weak0虚引用(PhantomReference)“虚引用”顾名思义,就是形同虚设,Unlikeothertypesofreferences,virtualreferencesdonotdeterminethelife一个对象的循环。如果一个对象只持有虚引用,那么它随时都可能被垃圾回收器回收,就像没有引用一样。幻象引用主要用于跟踪被垃圾收集器回收的对象的活动。幻影引用与软引用和弱引用的区别之一是幻影引用必须与引用队列(ReferenceQueue)结合使用。当垃圾回收器要回收一个对象时,如果发现它还有一个虚引用,就会把这个虚引用添加到与之关联的引用队列中,然后再回收该对象的内存。**总结Java4的引用等级从高到低依次为:强引用>软引用>弱引用>虚引用有些对象会被回收,有些不会。垃圾回收器会从根对象Object中标记存活下来的对象,然后回收一些不可达的对象和一些被引用的对象。我们用表格来说明一下,如下:弱引用和弱引用在实际编程中很少用到。虚引用经常使用软引用。这是因为软引用可以加快JVM对垃圾内存的回收,维护系统的安全,防止内存溢出(OutOfMemory)等问题。PS:这里有技术交流群(QQ群号:1158819530),方便大家一起交流,不断学习,共同进步。如果需要,您可以添加它。