強、軟、弱、虛四大引用示例
阿新 • • 發佈:2020-08-08
一、強引用
我們日常使用的都是強引用
,如下:
StringBuffer str = new StringBuffer("Hello World")
強引用的特點:
- 強引用可以直接訪問目標物件
- 強引用所指向的物件在任何時候都不會被垃圾回收,虛擬機器寧願報OOM,也不會回收強引用所指向的物件
- 強引用可能會導致記憶體洩漏
二、弱引用
特點:
- 當堆空間不足時,就會被回收
使用示例
/** * 虛擬機器引數:-Xmx10m * 軟引用配合引用佇列使用,自動入隊;也可以不配合引用佇列使用 * @Author Helius * @Create 2020-08-08-6:32 下午 */ public class SoftRefQ { public static class User { int id; String name; public User(int id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "[id = " + id + ", name = " + name + "]"; } } static ReferenceQueue<User> softQueue = null; public static class CheckRefQueue extends Thread{ @Override public void run() { while (true) { if (softQueue != null) { UserSoftReference obj = null; try { obj =(UserSoftReference) softQueue.remove(); } catch (InterruptedException e) { e.printStackTrace(); } if (obj != null) { System.out.println("user id " + obj.uid + " is delete"); } } } } } public static class UserSoftReference extends SoftReference<User> { int uid; public UserSoftReference(User referent, ReferenceQueue<? super User> q) { super(referent, q); this.uid = referent.id; } } public static void main(String[] args) throws InterruptedException { Thread t = new CheckRefQueue(); t.setDaemon(true); t.start(); User u = new User(1,"mary"); softQueue = new ReferenceQueue<>(); UserSoftReference userSoftReference = new UserSoftReference(u, softQueue); u = null; System.out.println(userSoftReference.get()); System.gc(); System.out.println("After GC"); System.out.println(userSoftReference.get()); System.out.println("try to create byte array and GC"); byte[] b = new byte[1024 * 925 * 7]; System.gc(); System.out.println(userSoftReference.get()); Thread.sleep(1000); } }
三、弱引用
特點
只要有GC
就會被回收,一般配合引用佇列使用。
非常使用用來保持可有可無的快取資料
使用示例:
public class WeakRef { public static class User { int id; String name; public User(int id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "[id = " + id + ", name = " + name + "]"; } } public static void main(String[] args) { User u = new User(1,"mary"); WeakReference<User> userWeakRef = new WeakReference<>(u); u = null; System.out.println(userWeakRef.get()); System.gc(); //不管當前記憶體空間足夠與否,都會回收它的記憶體 System.out.println("After GC:"); System.out.println(userWeakRef.get()); } }
輸出:
[id = 1, name = mary]
After GC:
null
四、虛引用
一個持有虛引用 的物件,和沒有引用幾乎是一樣的,隨時可能被垃圾器回收,當試圖通過虛引用get()方法取得強引用時,總是會失敗。
一般和引用佇列一起使用,
使用示例:
public class TraceCanReliveObj { public static TraceCanReliveObj obj; static ReferenceQueue<TraceCanReliveObj> phantomQueue = null; public static class CheckRefQueue extends Thread { @Override public void run() { while (true) { if (phantomQueue != null) { PhantomReference<TraceCanReliveObj> objt = null; try { objt = (PhantomReference<TraceCanReliveObj>) phantomQueue.remove(); } catch (InterruptedException e) { e.printStackTrace(); } if (objt != null) { System.out.println("TraceCanReliveObj is delete"); } } } } } @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("CanReliveObj finalize called"); obj = this; } @Override public String toString() { return "I am CanReliveObj"; } public static void main(String[] args) throws InterruptedException { Thread t = new CheckRefQueue(); t.setDaemon(true); t.start(); phantomQueue = new ReferenceQueue<>(); obj = new TraceCanReliveObj(); //構造虛引用 PhantomReference<TraceCanReliveObj> phantomRef = new PhantomReference<>(obj,phantomQueue); obj = null; System.gc(); Thread.sleep(1000); if (obj == null) { System.out.println("obj is null"); } else { System.out.println("obj 可用"); } System.out.println("第2次 GC"); obj = null; System.gc(); Thread.sleep(1000); if (obj == null) { System.out.println("obj is null"); } else { System.out.println("obj 可用"); } } }
輸出:
CanReliveObj finalize called
obj 可用
第2次 GC
TraceCanReliveObj is delete
obj is null
五、小結:
應付面試爾。