java中的WeakReference(弱引用)

java中的weakReference-弱引用

1.介绍

阅读ThreadLocal源码中,其中嵌套类ThreadLocalMap中的Entry继承了WeakReferenc,为了能搞明白ThreadLocal,需要对类WeakReference进一步认识。WeakReference如字面意思,弱引用, 当一个对象仅仅被weak reference(弱引用)指向, 而没有任何其他strong reference(强引用)指向的时候, 如果这时GC运行, 那么这个对象就会被回收,不论当前的内存空间是否足够,这个对象都会被回收。

2.类WeakReference源码

public class WeakReference<T> extends Reference<T> {

    /**
     * Creates a new weak reference that refers to the given object.  The new
     * reference is not registered with any queue.
     *
     * @param referent object the new weak reference will refer to
     */
    public WeakReference(T referent) {
        super(referent);
    }

    /**
     * Creates a new weak reference that refers to the given object and is
     * registered with the given queue.
     *
     * @param referent object the new weak reference will refer to
     * @param q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     */
    public WeakReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

}

  • WeakReference(T referent):referent就是被弱引用的对象。

  • WeakReference(T referent, ReferenceQueue<? super T> q):referent就是被弱引用的对象,ReferenceQueue队列,当对象referent被系统GC回收时,对象本身(继承WeakReference的对象或WeakReference对象)自动加入ReferenceQueue队列当中。

  • 注意:弱引用对象是WeakReference(referentObject) 中的 referentObject 对象,并不是继承WeakReference的子类

3.例子

3.1 WeakReference 示例1

java类:Computer

/**
 * @author
 */
public class Computer {

    private String name;

    public Computer(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * 覆盖finalize,在对象被GC回收的时候会自动执行。
     * @throws Throwable
     */
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("Computer GC:  " + name + " finalize!");
    }

    @Override
    public String toString() {
        return "Computer{" +
                "name='" + name + '\'' +
                '}';
    }
}

java类:Product

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

/**
 * 产品
 * 注意:弱引用对象是传入泛型T,不是类Product
 * @author
 */
public class Product<T> extends WeakReference {

    public Product(T referent) {
        super(referent);
    }

    public Product(Object referent, ReferenceQueue q) {
        super(referent, q);
    }
}

Main.test1()方法

public class Main {

    public static void main(String[] args) {
        test1();
    }

    public static void test1() {
        Product product = new Product(new Computer("dell"));
        System.out.println(product);
        System.out.println(product.get());
        System.out.println("gc之前");
        // 执行gc,内存回收
        System.gc();
        // 睡眠1s,等待系统回收内存
        try {
            System.out.println("等待1s...");
            Thread.sleep(1000L);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("gc之后");
        System.out.println(product);
        System.out.println(product.get());
    }
}

执行输出

# product引用对象
test1.Product@1b6d3586
# product.computer弱引用对象输出
Computer{name='dell'}
gc之前
等待1s...
# computer对象自动回收方法回调
Computer GC:  dell finalize!
gc之后
# product引用对象
test1.Product@1b6d3586
# product.computer弱引用对象输出
null

结论:

  1. 弱引用对象是WeakReference(referentObject) 中的 referentObject 对象。
  2. JVM,自动GC或者是手动GC, 不论当前的内存空间是否足够,弱引用对象都会被回收。
  3. 其他,弱引用对象在使用时要严谨,可能会造成内存泄漏,造成内存浪费;ThreadLocal会造成内存泄漏。

3.2 WeakReference 示例2

ReferenceQueue的使用

public class Main {

    public static void main(String[] args) {
        test2();
    }

    public static void test2() {

        ReferenceQueue<Computer> referenceQueue = new ReferenceQueue<>();
        WeakReference<Computer> weakReference1 = new WeakReference<Computer>(new Computer("Dell"), referenceQueue);
        WeakReference<Computer> weakReference2 = new WeakReference<Computer>(new Computer("Apple"), referenceQueue);

        System.out.println("=====gc调用前=====");
        Reference<? extends Computer> reference1 = null;
        while ((reference1 = referenceQueue.poll()) != null) {
            System.out.println(reference1);
        }
        System.out.println(weakReference1);
        System.out.println(weakReference2);
        System.out.println(weakReference1.get());
        System.out.println(weakReference2.get());

        System.out.println("=====调用gc=====");
        System.gc();
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("=====gc调用后=====");

        //下面两个输出为null,表示对象被回收了
        System.out.println(weakReference1.get());
        System.out.println(weakReference2.get());

        //输出结果,并且就是上面的appleWeakReference、appleWeakReference2,再次证明对象被回收了
        Reference<? extends Computer> reference2 = null;
        while ((reference2 = referenceQueue.poll()) != null) {
            //如果使用继承的方式就可以包含其他信息了
            System.out.println("referenceQueue:" + reference2);
        }
    }

输出

=====gc调用前=====
java.lang.ref.WeakReference@39a054a5
java.lang.ref.WeakReference@71bc1ae4
Computer{name='Dell'}
Computer{name='Apple'}
=====调用gc=====
Computer GC:  Apple finalize!
Computer GC:  Dell finalize!
=====gc调用后=====
null
null
referenceQueue:java.lang.ref.WeakReference@39a054a5
referenceQueue:java.lang.ref.WeakReference@71bc1ae4

结论:

  1. ReferenceQueue队列,当对象referent被系统GC回收时,继承WeakReference的对象或WeakReference对象自动加入ReferenceQueue队列当中。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值