Java強軟弱虛引用Referencehtml
學習過程記錄,加深理解,提高文字組合表達能力。也但願能給學習Reference的同窗一些靈感java
源碼基於jdk1.8.0_111:api
由代碼量上也能夠初步判斷,Java引用,並不太複雜緩存
Package java.lang.ref:網絡
提供引用對象類,它支持與垃圾收集器進行有限程度的交互。oracle
Provides reference-object classes, which support a limited degree of interaction with the garbage collector. --oracle.comless
java.lang.ref包中提供了幾個類:SoftReference類、WeakReference類和PhantomReference類,它們分別表明軟引用、弱引用和虛引用。ReferenceQueue類表示引用隊列,它能夠和這三種引用類聯合使用,以便跟蹤Java虛擬機回收所引用的對象的活動。ide
SoftReference:軟引用–>當虛擬機內存不足時,將會回收它指向的對象;須要獲取對象時,能夠調用get方法。函數
能夠經過java.lang.ref.SoftReference使用軟引用。一個持有軟引用的對象,不會被JVM很快回收,JVM會根據當前堆的使用狀況來判斷什麼時候回收。當堆的使用率臨近閾值時,纔會回收軟引用的對象。學習
例如從網絡上獲取圖片,而後將獲取的圖片顯示的同時,經過軟引用緩存起來。當下次再去網絡上獲取圖片時,首先會檢查要獲取的圖片緩存中是否存在,若存在,直接取出來,不須要再去網絡上獲取。
在垃圾回收器對這個Java對象回收前,SoftReference類所提供的get方法會返回Java對象的強引用,一旦垃圾線程回收該Java對象以後,get方法將返回null。因此在獲取軟引用對象的代碼中,必定要判斷是否爲null,以避免出現NullPointerException異常致使應用崩潰。
public class SoftReference<T> extends Reference<T> { /** * Timestamp clock, updated by the garbage collector */ static private long clock; /** * Timestamp updated by each invocation of the get method. The VM may use * this field when selecting soft references to be cleared, but it is not * required to do so. */ private long timestamp; /** * Creates a new soft reference that refers to the given object. The new * reference is not registered with any queue. * * @param referent object the new soft reference will refer to */ public SoftReference(T referent) { super(referent); this.timestamp = clock; } /** * Creates a new soft reference that refers to the given object and is * registered with the given queue. * * @param referent object the new soft reference will refer to * @param q the queue with which the reference is to be registered, * or <tt>null</tt> if registration is not required * */ public SoftReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); this.timestamp = clock; } /** * Returns this reference object's referent. If this reference object has * been cleared, either by the program or by the garbage collector, then * this method returns <code>null</code>. * * @return The object to which this reference refers, or * <code>null</code> if this reference object has been cleared */ public T get() { T o = super.get(); if (o != null && this.timestamp != clock) this.timestamp = clock; return o; } }
若是一個對象只具備弱引用,那麼在垃圾回收器線程掃描的過程當中,一旦發現了只具備弱引用的對象,無論當前內存空間足夠與否,都會回收它的內存。不過,因爲垃圾回收器是一個優先級很低的線程,所以不必定會很快發現那些只具備弱引用的對象。
弱引用也能夠和一個引用隊列(ReferenceQueue)聯合使用,若是弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。
同軟引用SoftReference
public class WeakReference<T> extends Reference<T> { /** * Creates a new weak reference that refers to the given object. The new * reference is not registered with any queue. * * @param referent object the new weak reference will refer to */ public WeakReference(T referent) { super(referent); } /** * Creates a new weak reference that refers to the given object and is * registered with the given queue. * * @param referent object the new weak reference will refer to * @param q the queue with which the reference is to be registered, * or <tt>null</tt> if registration is not required */ public WeakReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } }
沒有其餘代碼,GC時被回收掉。
虛引用是全部引用類型中最弱的一個。一個持有虛引用的對象,和沒有引用幾乎是同樣的,隨時均可能被垃圾回收器回收。當試圖經過虛引用的get()方法取得強引用時,老是會失敗。而且,虛引用必須和引用隊列一塊兒使用,它的做用在於跟蹤垃圾回收過程。 當垃圾回收器準備回收一個對象時,若是發現它還有虛引用,就會在垃圾回收後,銷燬這個對象,獎這個虛引用加入引用隊列。
未遇到
public class PhantomReference<T> extends Reference<T> { /** * Returns this reference object's referent. Because the referent of a * phantom reference is always inaccessible, this method always returns * <code>null</code>. * * @return <code>null</code> */ public T get() { return null; } /** * Creates a new phantom reference that refers to the given object and * is registered with the given queue. * * <p> It is possible to create a phantom reference with a <tt>null</tt> * queue, but such a reference is completely useless: Its <tt>get</tt> * method will always return null and, since it does not have a queue, it * will never be enqueued. * * @param referent the object the new phantom reference will refer to * @param q the queue with which the reference is to be registered, * or <tt>null</tt> if registration is not required */ public PhantomReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } }
實現了鏈表結構的隊列
當系統要回收Reference持有的對象引用referent的時候,Reference的enqueue函數會被調用,而在這個函數中調用了ReferenceQueue的enqueue函數。
Reference與引用隊列(ReferenceQueue)聯合使用,若是弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。
對本文有什麼建議(內容、寫做風格等),歡迎留言提出,感謝!