强、软、弱、虚四大引用示例

一、强引用

我们日常使用的都是强引用,如下:

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

五、小结:

应付面试尔。

posted @ 2020-08-08 20:50  HeliusKing  阅读(512)  评论(0编辑  收藏  举报