• java多线程_Java中的引用类型


      java中的引用分为4种,分别是:1.强引用;2.软引用;3.弱引用;4.虚引用。四种引用分别有各自的特点,下面分别通过代码对四种类型的引用进行一下测试。

    1.强引用

      强引用是我们平时最常用的一种引用类型。在对象被引用的时候,不会被gc的垃圾回收器回收。当没有引用时,堆中对象会被回收。

      示范代码:

     1 /**
     2  * 验证垃圾回收机制类
     3  * @author 
     4  *
     5  */
     6 public class M {
     7     // 重写finalize 方法,该方法是Object对象的方法,在对象被回收时执行。
     8     // 平时开发不建议在该位置写代码,容易导致OOM问题
     9     @Override
    10     protected void finalize() {
    11         System.out.println("finalize");
    12     }
    13 }
    验证类
     1 import java.io.IOException;
     2 /**
     3  * 强引用 普通的引用
     4  * 
     5  * 栈里的小m指向堆里的M对象,这个引用叫做强引用,只有没有任何引用指向对象的时候,对象才会被垃圾回收器回收
     6  * @author Lys
     7  *
     8  */
     9 public class T01_NormalReference {
    10     public static void main(String[] args) throws IOException {
    11         M m = new M();
    12         m=null;
    13         System.gc();
    14         
    15         System.in.read();
    16     }
    17 }

    运行结果:

    finalize
    
    // 说明引用在被置为null 后,在系统gc的时候,对象被垃圾回收器回收了 

    2.软引用

      只被软引用所引用的对象,会在jvm内存不够用的时候,被垃圾回收器回收。通过下面的测试代码我们可以看出:在m刚被定义的时候,这个时候m还是可以get到值的,然后调用系统gc,m对象也没有被垃圾回收器回收。但是当定义其他对象使内存不够用的时候,该对象就被回收掉了。该引用适用场景:一个比较大的缓存对象,经常需要读取。当系统空间足够的时候,就将其缓存在jvm中,当可用空间不足的时候,就将其回收掉。

      示范代码:

     1 /**
     2  * 软引用
     3  * 
     4  * 软应用内的对象会随着空间不够用而消失,一般应用于缓存。
     5  * @author Lys
     6  *
     7  */
     8 public class T02SoftReference {
     9     public static void main(String[] args) {
    10         SoftReference<byte[]> m = new SoftReference<>(new byte[1024*1024*10]);
    11 
    12         System.out.println(m.get());
    13         System.gc();
    14         try {
    15             Thread.sleep(500);
    16         } catch (Exception e) {
    17             e.printStackTrace();
    18         }
    19         System.out.println(m.get());
    20         byte[] b = new byte[1024*1024*3];
    21         byte[] b1 = new byte[1024*1024*3];
    22         System.out.println(m.get());
    23     }
    24 }

      代码执行参数:-Xmx20M

      代码执行结果:

    [B@15db9742
    [B@15db9742
    null
    
    // 前两个打印输出证明在内存足够的情况下不会被回收,第三个输出表示,当内存不足时,软引用的对象就被垃圾回收器回收了

    3.弱引用

      只有弱引用引用的对象在遇到垃圾回收器执行垃圾回收的时候,就会被回收。弱引用的应用场景:ThreadLocal 对象在调用set方法,在存储对象的时候。本身将当前线程局部变量对象作为key值,存入线程的ThreadLocalMap中,被set的值作为ThreadLocalMap的value。jdk源代码如下:

        static class ThreadLocalMap {
    
            /**
             * The entries in this hash map extend WeakReference, using
             * its main ref field as the key (which is always a
             * ThreadLocal object).  Note that null keys (i.e. entry.get()
             * == null) mean that the key is no longer referenced, so the
             * entry can be expunged from table.  Such entries are referred to
             * as "stale entries" in the code that follows.
             */
            static class Entry extends WeakReference<ThreadLocal<?>> {
                /** The value associated with this ThreadLocal. */
                Object value;
    
                Entry(ThreadLocal<?> k, Object v) {
                    super(k);
                    value = v;
                }
            }

      这里的super(key)创建了一个弱引用,当ThreadLocal 对象在栈中的引用消失后,这个对象就会被垃圾回收器回收,而不必担心出现内存泄漏问题。

    示范代码:

    /**
     * 验证垃圾回收机制的对象
     * @author 
     *
     */
    public class M {
        // 重写finalize 方法,该方法是Object对象的方法,在对象被回收时执行。
        // 平时开发不建议在该位置写代码,容易导致OOM问题
        @Override
        protected void finalize() {
            System.out.println("finalize");
        }
    }
    验证对象
    import java.lang.ref.WeakReference;
    import java.util.WeakHashMap;
    /**
     * 弱引用 垃圾回收器看到后就回收 ,,就会被回收
     * 应用场景:ThreadLocal 解决内存泄漏问题 ,但是用户自己创建的value还存在,所以tl中创建的内容,在tl不用以后,要进行remove操作。
     * @author Lys
     *
     */
    public class T03_WeakRefernce {
        public static void main(String[] args) {
            WeakReference<M> m = new WeakReference<M>(new M());
            System.out.println(m.get());
            System.gc();
            System.out.println(m.get());
            
           //  ThreadLocal<M> tl = new ThreadLocal<>();
            // tl.set(new M());
            // tl.remove();
    
        }
    }

    代码执行结果:

    reference.M@15db9742
    null
    finalize

    4.虚引用

      虚引用在jvm 中没有内存,用于管理在虚拟机之外的内存。如下图所示,虚引用必须当我们的虚拟机需要管理一块不存在于jvm的内存时,需要跟踪对象的垃圾回收状态,如果对象被回收了,那么将该对象的引用放入queue,根据queue中取出的对象去将对应的JVM外面的内存进行操作。

     示范代码:

     1 /**
     2  * 虚引用 get不到,随时被回收的对象
     3  * 
     4  * 作用:管理堆外内存NIO
     5  * @author Lys
     6  *
     7  */
     8 
     9 import java.lang.ref.PhantomReference;
    10 import java.lang.ref.Reference;
    11 import java.lang.ref.ReferenceQueue;
    12 import java.util.LinkedList;
    13 import java.util.List;
    14 
    15 public class T04_phantomReference {
    16 private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();
    17     public static void main(String[] args) {
    18         PhantomReference<M> phantomReference = new PhantomReference<M>(new M(),QUEUE );
    19         
    20         new Thread(()->{
    21             
    22                 try {
    23                     System.gc();
    24                     Thread.sleep(1000);
    25                 } catch (Exception e) {
    26                     e.printStackTrace();
    27                     Thread.currentThread().interrupt();
    28                 }
    29                 System.out.println(phantomReference.get());
    30                 System.gc();
    31             
    32         }).start();
    33         
    34         new Thread(()->{
    35             while (true) {
    36                 Reference<? extends M> poll = QUEUE.poll();
    37                 if (poll!=null) {
    38                     
    39                     System.out.println("----- 虚引用对象被jvm回收-------"+poll);
    40                 }
    41             }
    42         }).start();
    43     }
    44 }

    执行结果:

    finalize
    null
    ----- 虚引用对象被jvm回收-------java.lang.ref.PhantomReference@4a140fe5

  • 相关阅读:
    Highmaps网页图表教程之图表配置项结构与商业授权
    架构要素--安全性
    Select * 一定不走索引是否正确?
    uvalive 6669 hidden tree(好壮压dp)
    KVM硬件辅助虚拟化之 EPT in Nested Virtualization
    HDU 1043 八数码(A*搜索)
    在夕阳再晨的日子里(二)----掌管市场部的岁月之合作团队与社区的拓展
    Android开发数据库之第三方ORM框架(GreenDao)
    【MySQL】常见错误与经常使用命令的集锦
    Service-监听手机来电
  • 原文地址:https://www.cnblogs.com/liyasong/p/reference.html
Copyright © 2020-2023  润新知