类与对象:强软弱虚引用

强引用

强引用是最普遍的一种引用,我们写的代码,99.9999%都是强引用

在实际的开发中,看到有一些对象被手动赋值为NULL,很大可能就是为了“特意提醒”JVM这块资源可以进行垃圾回收了

软引用

 SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());

软引用就是把对象用SoftReference包裹一下,当我们需要从软引用对象获得包裹的对象,只要get一下就可以了:

SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());
Student student = studentSoftReference.get();
System.out.println(student);

软引用有什么特点呢:当内存不足,会触发JVM的GC,如果GC后,内存还是不足,就会把软引用的包裹的对象给干掉,也就是只有在内存不足,JVM才会回收该对象。

软引用到底有什么用呢?比较适合用作缓存,当内存足够,可以正常的拿到缓存,当内存不够,就会先干掉缓存,不至于马上抛出OOM。

 

弱引用

弱引用的使用和软引用类似,只是关键字变成了WeakReference:

 

WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1024*1024*10]);
System.out.println(weakReference.get());

触发了GC,资源还是被回收了。弱引用在很多地方都有用到,比如ThreadLocal、WeakHashMap。

虚引用

虚引用又被称为幻影引用,我们来看看它的使用:

ReferenceQueue queue = new ReferenceQueue();
PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);
System.out.println(reference.get());

虚引用的使用和上面说的软引用、弱引用的区别还是挺大的,我们先不管ReferenceQueue 是个什么鬼,直接来运行:

null
竟然打印出了null,我们来看看get方法的源码:

public T get() {
return null;
}

这是几个意思,竟然直接返回了null。

这就是虚引用特点之一了:无法通过虚引用来获取对一个对象的真实引用。

创建虚引用对象,我们除了把包裹的对象传了进去,还传了一个ReferenceQueue,从名字就可以看出它是一个队列。

虚引用的特点之二就是

虚引用必须与ReferenceQueue一起使用,当GC准备回收一个对象,如果发现它还有虚引用,就会在回收之前,把这个虚引用加入到与之关联的ReferenceQueue中

eg:

   ReferenceQueue queue = new ReferenceQueue();
        List<byte[]> bytes = new ArrayList<>();
        PhantomReference<Student> reference = new PhantomReference<Student>(new Student(),queue);
        new Thread(() -> {
            for (int i = 0; i < 100;i++ ) {
                bytes.add(new byte[1024 * 1024]);
            }
        }).start();

        new Thread(() -> {
            while (true) {
                Reference poll = queue.poll();
                if (poll != null) {
                    System.out.println("虚引用被回收了:" + poll);
                }
            }
        }).start();
        Scanner scanner = new Scanner(System.in);
        scanner.hasNext();
    }

运行结果:

Student 被回收了
虚引用被回收了:java.lang.ref.PhantomReference@1ade6f1

我们简单的分析下代码:

第一个线程往集合里面塞数据,随着数据越来越多,肯定会发生GC。

第二个线程死循环,从queue里面拿数据,如果拿出来的数据不是null,就打印出来。

从运行结果可以看到:当发生GC,虚引用就会被回收,并且会把回收的通知放到ReferenceQueue中。

虚引用有什么用呢?在NIO中,就运用了虚引用管理堆外内存。

 

 

 

 

posted @ 2021-02-26 08:43  弱水三千12138  阅读(51)  评论(0)    收藏  举报