强软弱虚引用

1.强引用 

package com.cjian.threadlocal;

import java.io.IOException;

/**
 * @description:强引用
 * @author: cWX969834
 * @time: 2020/11/12 18:52
 */
public class NormalReferenceTest {

    public static void main(String[] args) throws IOException {
        Person p = new Person();//类似这种直接指向一个对象的的为强引用
        p = null;// p与new Person()之间的强应用被断开,此时,new Person() 是一个垃圾
        System.gc();
        //阻塞main线程,给垃圾回收线程时间去执行
        System.in.read();

    }

    static class Person{
        @Override
        protected void finalize() throws Throwable {
            //一个对象被回收的时候,会调用到该方法
            System.out.println("finalize...");

            //官方是不建议我们重写该方法的,该方法如果执行时间过长,会使对象回收速度变慢,会导致FGC、OOM
        }
    }

}

输出:

finalize...

2.软引用

package com.cjian.threadlocal;

import java.lang.ref.SoftReference;

/**
 * @description:软引用
 * @author: cWX969834
 * @time: 2020/11/12 19:00
 */
public class SoftReferenceTest {
    public static void main(String[] args) throws InterruptedException {
        //sr  与new SoftReference之间还是一个强引用的,new SoftReference 与new byte[1014*1014*10]之间是一个软引用
        SoftReference<byte[]> sr = new SoftReference<>(new byte[1014*1014*10]);

        //获取
        System.out.println(sr.get());

        System.gc();

        Thread.sleep(1000);

        System.out.println(sr.get());

        //再分配一个数组,我们通过vm参数将堆内存大小设置为20M,由于之前sr已经占据了10M,这里会不够分,才会去回收sr
        //这里就又是一个强引用
        //byte[] b = new byte[1014*1014*15];

        //通过验证的得知,内存够时,软引用不会被回收,内存不够用时,软引用才会被回收

        //再次获取sr
        //System.out.println("-->"+sr.get());
    }


}

输出:

[B@29453f44
[B@29453f44

当我们放开最下面的两行代码的时候,并将堆最大值设为24M(-Xmx24M)时,输出如下:

PS:这里在验证的时候本想着设置20M的,但是报了OOM,可能是因为堆内有其他的一些对象,占用了一点内存,调制24M,结果才正确

[B@29453f44
[B@29453f44
-->null

 软引用非常适合做缓存

3.弱引用

package com.cjian.threadlocal;

import java.lang.ref.WeakReference;

/**
 * @description:弱引用
 * @author: cWX969834
 * @time: 2020/11/12 18:50
 */
public class WeakReferenceTest {

    public static void main(String[] args) {
        WeakReference<Person> wr = new WeakReference<>(new Person());
        System.out.println(wr.get());
        System.gc();
        System.out.println(wr.get());
    }

    static class Person{
        @Override
        protected void finalize() throws Throwable {
            //一个对象被回收的时候,会调用到该方法
            System.out.println("finalize...");

            //官方是不建议我们重写该方法的,该方法如果执行时间过长,会使对象回收速度变慢,会导致FGC、OOM
        }
    }

}

输出:

com.cjian.threadlocal.WeakReferenceTest$Person@29453f44
null
finalize...

可知,弱引用在垃圾回收的时候是直接被回收的,那有什么用呢?这也是难点!

4.虚引用

了解即可,知识补充可去学习Netty

package com.cjian.threadlocal;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.util.LinkedList;
import java.util.List;

/**
 * @description:虚引用
 * @author: cWX969834
 * @time: 2020/11/12 19:59
 */
public class PhantomReferenceTest {
    private static final List<Object> LIST = new LinkedList<>();
    private static final ReferenceQueue<Person> QUEUE = new ReferenceQueue<>();
    public static void main(String[] args) {

        PhantomReference<Person> pr = new PhantomReference<>(new Person(), QUEUE);
        System.out.println(pr.get());

    }
    static class Person{
        @Override
        protected void finalize() throws Throwable {
            //一个对象被回收的时候,会调用到该方法
            System.out.println("finalize...");

            //官方是不建议我们重写该方法的,该方法如果执行时间过长,会使对象回收速度变慢,会导致FGC、OOM
        }
    }
}

输出:

null

这是什么鬼?拿都拿不到,有啥用? 

管理直接内存:

虚引用指向的对象在被回收的时候,会将引用放在一个队列里(存信号),然后回收的时候是通过队列回收的,需要JVM特殊处理(回收这个引用指向的直接内存)

package com.cjian.threadlocal;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.LinkedList;
import java.util.List;

/**
 * @description:虚引用
 * @author: cWX969834
 * @time: 2020/11/12 19:59
 */
public class PhantomReferenceTest {
    private static final List<Object> LIST = new LinkedList<>();
    private static final ReferenceQueue<Person> QUEUE = new ReferenceQueue<>();
    public static void main(String[] args) {

        PhantomReference<Person> pr = new PhantomReference<>(new Person(), QUEUE);
        System.out.println(pr.get());

        new Thread(()->{
            while(true){
                LIST.add(new byte[1024*1024]);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("--->"+pr.get());
            }
        }).start();
        new Thread(()->{
            while(true){
                Reference<? extends Person> poll = QUEUE.poll();
                if(poll!=null){

                System.out.println("虚引用被jvm回收了--->"+poll);
                }
            }
        }).start();


    }
    static class Person{
        @Override
        protected void finalize() throws Throwable {
            //一个对象被回收的时候,会调用到该方法
            System.out.println("finalize...");

            //官方是不建议我们重写该方法的,该方法如果执行时间过长,会使对象回收速度变慢,会导致FGC、OOM
        }
    }
}
null
--->null
--->null
--->null
--->null
--->null
--->null
--->null
--->null
--->null
--->null
finalize...
--->null
--->null
--->null
--->null
--->null
虚引用被jvm回收了--->java.lang.ref.PhantomReference@6a77f9ce
--->null
--->null
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
	at com.cjian.threadlocal.PhantomReferenceTest.lambda$main$0(PhantomReferenceTest.java:28)
	at com.cjian.threadlocal.PhantomReferenceTest$$Lambda$1/1828972342.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值