1. 程式人生 > 實用技巧 >強、軟、弱、虛四大引用示例

強、軟、弱、虛四大引用示例

一、強引用

我們日常使用的都是強引用,如下:

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

五、小結:

應付面試爾。