我是在什么情况下遇到了这部分知识?
在我看Glide源码学习它的缓存机制的时候,遇到类ActiveResources
,这个类里面用一个Map<Key, ResourceWeakReference>
的方式保存下缓存数据,然后这个ResourceWeakReference
是继承自WeakReference
,然后在代码里面还开了一个线程,里面有一个死循环一直在监听resourceReferenceQueue
这个队列的数据。然后就很纳闷,然后去百度了下。发现这是弱引用的知识,当发生gc的时候,弱引用对象会被保存到resourceReferenceQueue这个队列里面。这个队列是线程阻塞的,只有当有数据的时候才会继续执行。这也是一个知识点。我们就可以利用这一点用来监听发生gc的时候移除的引用对象数据。完美
当一个对象仅仅被weak referencr指向的时候,而没有任何其他强引用指向的时候。如果这个时候触发了GC,那么这个对象就会被回收,不论当前的内存空间是否够用,这个对象都会被回收。
认识WeakReference
:
WeakReference
继承Reference
1 2 3 4 5 6 7 8
| public class WeakReference<T> extends Reference<T> { public WeakReference(T referent) { super(referent); } public WeakReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } }
|
这里有两个构造函数,我来分别讲下构造函数里面的参数信息:
- referent:通过对他的翻译我们知道他是:所指对象的意思。就是我们弱引用的对象。(需要区分弱引用对象和被弱引用的对应),弱引用对象指的是
WeakReference
的实例或者其子类的实例。
- q:ReferenceQueue:从名字也可以看出这是一个队列。他是在发生GC的时候,弱引用对象会被保存到这个队列里面。多以我们就可以通过这个监听这个队列的数据变化,来获取被gc的弱引用对象值。
案例
使用WeakReference
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package io.github.brightloong.lab.reference; public class Apple {
private String name;
public Apple(String name) { this.name = name; }
@Override protected void finalize() throws Throwable { super.finalize(); System.out.println("Apple: " + name + " finalize。"); }
@Override public String toString() { return "Apple{" + "name='" + name + '\'' + '}' + ", hashCode:" + this.hashCode(); } }
|
继承WeakReference的Salad:
1 2 3 4 5 6 7
| package io.github.brightloong.lab.reference; import java.lang.ref.WeakReference; public class Salad extends WeakReference<Apple> { public Salad(Apple apple) { super(apple); } }
|
Client调用和输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package io.github.brightloong.lab.reference; import java.lang.ref.WeakReference; public class Client { public static void main(String[] args) { Salad salad = new Salad(new Apple("红富士")); System.out.println("Apple:" + salad.get()); System.gc(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }
if (salad.get() == null) { System.out.println("clear Apple。"); } } }
|
ReferenceQueue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package io.github.brightloong.lab.reference;
import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; public class Client2 { public static void main(String[] args) { ReferenceQueue<Apple> appleReferenceQueue = new ReferenceQueue<>(); WeakReference<Apple> appleWeakReference = new WeakReference<Apple>(new Apple("青苹果"), appleReferenceQueue); WeakReference<Apple> appleWeakReference2 = new WeakReference<Apple>(new Apple("毒苹果"), appleReferenceQueue);
System.out.println("=====gc调用前====="); Reference<? extends Apple> reference = null; while ((reference = appleReferenceQueue.poll()) != null ) { System.out.println(reference); } System.out.println(appleWeakReference); System.out.println(appleWeakReference2); System.out.println(appleWeakReference.get()); System.out.println(appleWeakReference2.get());
System.out.println("=====调用gc====="); System.gc(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("=====gc调用后=====");
System.out.println(appleWeakReference.get()); System.out.println(appleWeakReference2.get());
Reference<? extends Apple> reference2 = null; while ((reference2 = appleReferenceQueue.poll()) != null ) { System.out.println("appleReferenceQueue中:" + reference2); } } }
|
在Android里面的使用案例
可以看Glide
的源码里面的ActiveResources
类。