美文网首页
Java中的四种引用

Java中的四种引用

作者: 钢牙仔 | 来源:发表于2020-11-23 22:24 被阅读0次
        static class Person {
            String mName;
            public Person(String name) {
                mName = name;
            }
            @Override
            public String toString() {
                return "person[" + mName + "]";
            }
        }
    

    1.强软弱虚四种引用

    1.1 强引用

        public static void strongRef() {
            try {
                Person person = new Person("张三");
                Person strong = person;
                person = null;
                System.gc();
                Thread.sleep(1000);
                System.out.println(strong);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    执行结果:

    person[张三]
    

    解释:
    强引用是JVM的默认实现,即使内存不足会导致OOM(OutOfMemory)时,强引用关联的对象也不会被回收。

    1.2 软引用

           public static void softRef() {
                try {
                    Person person = new Person("李四");
                    ReferenceQueue<Person> rq = new ReferenceQueue<Person>();
                    SoftReference<Person> sr = new SoftReference<Person>(person, rq);
                    person = null;
                    System.gc();
                    Thread.sleep(1000);
                    System.out.println("sr.get():" + sr.get());
                    System.out.println("rq.poll():" + rq.poll());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    

    内存足够的情况下的执行结果:

    sr.get():person[李四]
    rq.poll():null
    

    内存不足的情况下的执行结果:

    sr.get():null
    rq.poll():java.lang.ref.SoftReference@15db9742
    

    解释:

    1. 某个对象只被软引用关联,当JVM内存不足时,该对象会被回收。也就是说在JVM抛出OutOfMemoryError之前,会去清理只被软引用关联的对象。
    2. 软引用可以与引用队列ReferenceQueue联合使用。当只被软引用关联的对象(即Person对象)被回收后,其相应的包装类对象(即SoftReference对象)会被加入到ReferenceQueue队列中。
    3. 包装类对象被加入到ReferenceQueue队列中后,调用其poll()方法可以获取该队列中的包装类对象。

    1.3 弱引用

        public static void weakRef() {
            try {
                Person person = new Person("王五");
                ReferenceQueue<Person> rq = new ReferenceQueue<Person>();
                WeakReference<Person> wr = new WeakReference<Person>(person, rq);
                System.out.println("wr.get():" + wr.get());
                person = null;
                Reference<?> reference;
                while (true) {
                    System.out.println("-----");
                    reference = rq.poll();
                    if (wr.equals(reference)) {
                        System.out.println("wr.get():" + wr.get());
                        System.out.println("被回收了");
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    执行结果:

    wr.get():person[王五]
    ----
    ----
    ----
    ...
    wr.get():null
    被回收了
    

    解释:
    当某个对象只被弱引用关联时,无论内存是否足够,只要 JVM 开始进行垃圾回收,该对象都会被回收。

    1.4 虚引用

        public static void phantomRef() {
            Person person = new Person("朱六");
            ReferenceQueue<Person> rq = new ReferenceQueue<>();
            PhantomReference<Person> pr = new PhantomReference<MyTest.Person>(person, rq);
            System.out.println("pr.get():" + pr.get());
            person = null;
            Reference<?> reference;
            while (true) {
                System.out.println("-----");
                reference = rq.poll();
                if (pr.equals(reference)) {
                    System.out.println("被回收了");
                    break;
                }
            }
        }   
    

    执行结果:

    pr.get():null
    -----
    -----
    -----
    ...
    被回收了
    

    解释:

    1. 虚引用必须与引用队列ReferenceQueue联合使用
    2. 虚引用的get()方法永远返回null
    3. 当JVM发现一个对象只被虚引用关联时,则会将虚引用加入ReferenceQueue队列中,然后当JVM垃圾回收时回收该对象

    注意:虚引用是先将包装类PhantomReference对象加入ReferenceQueue队列中,然后Person对象才被JVM回收;而软引用和弱引用则相反,是Person对象先被JVM回收,然后才...

    2.四种引用的应用场景:

    1. 强引用,不解释。
    2. 软引用,适用于网页、图片、视频等缓存。
      比如app内有一张图片,这张图片很多地方都会用到,如果每次用到的时候都去读取图片,大量的重复读取会导致性能下降,此时可以将图片缓存起来,需要的时候直接从内存中读取,但是由于图片占的内存空间比较大,缓存的图片过多就有可能发生OOM,这时就可以使用软引用。
    3. 弱引用,适用于可能会发生内存泄漏的地方。比如Android中的Handler,参见博客Android Handler详解
    4. 虚引用,在程序中可以判断PhantomReference是否已经被加入ReferenceQueue队列中,如果是,则说明虚引用关联的对象即将被回收,可以在回收之前执行一些必要的业务逻辑。

    相关文章

      网友评论

          本文标题:Java中的四种引用

          本文链接:https://www.haomeiwen.com/subject/rcjviktx.html