读书人

Java软件工程师应该知道的的四种引用

发布时间: 2012-10-17 10:25:47 作者: rapoo

Java程序员应该知道的的四种引用

图11-10 "hello"对象同时具有强引用和弱引用

在图11-10中,带实线的箭头表示强引用,带虚线的箭头表示弱引用。从图中可以看出,此时"hello"对象被str强引用,并且被一个WeakReference对象弱引用,因此"hello"对象不会被垃圾回收。
在以下程序代码中,把引用"hello"对象的str变量置为null,然后再通过WeakReference弱引用的get()方法获得"hello"对象的引用:

String str = new String("hello"); //①
ReferenceQueue<String> rq = new ReferenceQueue<String>(); //②
WeakReference<String> wf = new WeakReference<String>(str, rq); //③

str=null; //④取消"hello"对象的强引用
String str1=wf.get(); //⑤假如"hello"对象没有被回收,str1引用"hello"对象

//假如"hello"对象没有被回收,rq.poll()返回null
Reference<? extends String> ref=rq.poll(); //⑥

执行完以上第④行后,内存中引用与对象的关系如图11-11所示,此 时"hello"对象仅仅具有弱引用,因此它有可能被垃圾回收。假如它还没有被垃圾回收,那么接下来在第⑤行执行wf.get()方法会返 回"hello"对象的引用,并且使得这个对象被str1强引用。再接下来在第⑥行执行rq.poll()方法会返回null,因为此时引用队列中没有任 何引用。ReferenceQueue的poll()方法用于返回队列中的引用,如果没有则返回null。

Java软件工程师应该知道的的四种引用
图11-11 "hello"对象只具有弱引用

在以下程序代码中,执行完第④行后,"hello"对象仅仅具有弱引用。接下来两次调用System.gc()方法,催促垃圾回收器工作,从而提 高"hello"对象被回收的可能性。假如"hello"对象被回收,那么WeakReference对象的引用被加入到ReferenceQueue 中,接下来wf.get()方法返回null,并且rq.poll()方法返回WeakReference对象的引用。图11-12显示了执行完第⑧行后 内存中引用与对象的关系。

String str = new String("hello"); //①
ReferenceQueue<String> rq = new ReferenceQueue<String>(); //②
WeakReference<String> wf = new WeakReference<String>(str, rq); //③
str=null; //④

//两次催促垃圾回收器工作,提高"hello"对象被回收的可能性
System.gc(); //⑤
System.gc(); //⑥
String str1=wf.get(); //⑦ 假如"hello"对象被回收,str1为null
Reference<? extends String> ref=rq.poll(); //⑧

Java软件工程师应该知道的的四种引用
图11-12 "hello"对象被垃圾回收,弱引用被加入到引用队列

The important part about strong references -- the part that makes them "strong" -- is how they interact with the garbage collector. Specifically, if an object is reachable via a chain of strong references (strongly reachable), it is not eligible for garbage collection. As you don't want the garbage collector destroying objects you're working on, this is normally exactly what you want.

package com.TestRef;import java.lang.ref.PhantomReference;import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference;import java.lang.ref.WeakReference;import java.util.Map;import java.util.WeakHashMap;public class Ref {    public Ref() {    }    /**     * @param args     */    public static void main(String[] args) {        try {//            test1();//            test2();//            test3();//            test4();//            test5();            test6();        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    /** 强引用,JVM的默认实现 */      public static void test1() throws InterruptedException {          Object obj = new Object();          Object strong = obj;          obj = null;          System.gc();          Thread.sleep(1000);          System.out.println("strong="+strong);    }          /**      * WeakReference 弱引用( 当所引用的对象在 JVM 内不再有强引用时, GC 后weak reference 将会被自动回收)      * */      public static void test2() throws InterruptedException {          Object obj = new Object();          WeakReference<Object> wr = new WeakReference<Object>(obj);          obj = null;          System.gc();          Thread.sleep(1000);          System.out.println("wr.get()="+wr.get());          System.out.println("wr="+wr);          wr.clear();        System.out.println("w1111r="+wr.get());      }          /**      * SoftReference SoftReference 于 WeakReference 的特性基本一致, 最大的区别在于      * SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证)      * */      public static void test3() throws InterruptedException {          Object obj = new Object();          SoftReference<Object> sr = new SoftReference<Object>(obj);          obj = null;          System.gc();          Thread.sleep(1000);          System.out.println("sr.get()="+sr.get());      }          /**      * PhantomReference Phantom Reference(幽灵引用) 与 WeakReference 和 SoftReference      * 有很大的不同, 因为它的 get() 方法永远返回 null      * */      public static void test4() throws InterruptedException {          Object obj = new Object();          ReferenceQueue<Object> rq = new ReferenceQueue<Object>();          PhantomReference<Object> pr = new PhantomReference<Object>(obj, rq);          System.out.println("pr.get()="+pr.get());     }          /**     * ReferenceQueue:     * @throws InterruptedException     */    public static void test5() throws InterruptedException {          Object obj = new Object();          ReferenceQueue<Object> rq = new ReferenceQueue<Object>();          WeakReference<Object> pr = new WeakReference<Object>(obj, rq);          System.out.println("**pr.enqueue()="+pr.enqueue());          System.out.println("**pr.isEnqueued()="+pr.isEnqueued());              System.out.println("**pr="+pr);        System.out.println("**rq.poll()="+rq.poll());          obj = null;          System.gc();  //        System.out.println("pr.enqueue()="+pr.enqueue());  //        System.out.println("**pr.isEnqueued()="+pr.isEnqueued());      //        System.out.println("pr="+pr);//        System.out.println("rq.poll()="+rq.poll());  //        System.out.println("obj5="+obj);      }          /**      * 使用 WeakReference 作为 key, 一旦没有指向 key 的强引用,       * WeakHashMap 在 GC 后将自动删除相关的      * entry      */      public static void test6() throws InterruptedException {          Map<Object, Object> map = new WeakHashMap<Object, Object>();          Object key = new Object();          Object value = new Object();          map.put(key, value);                  key = null;          //        System.out.println("value="+value);  //        System.out.println("key="+key);  //        System.out.println("map.containsValue(value)="+map.containsValue(value)); //        System.out.println("map="+map);                  System.gc();          Thread.sleep(1000);                  System.out.println("value="+value);          System.out.println("key="+key);          System.out.println("map.containsValue(value)="+map.containsValue(value));         System.out.println("map="+map);      }  }

读书人网 >编程

热点推荐