Java弱引用之硬核复用机制
2020-04-13 本文已影响0人
风逝_c609
弱引用不是回收了吗?怎么还复用???下面咱们来一探究竟
1. 弱引用的常规使用
class Resource {
Object data;
public Resource(Object data) {
this.data = data;
}
public Object getData() {
return data;
}
}
写代码用弱引用测试一把
@Test
public void testWeakFirst() {
Resource resource = new Resource("data can re-use");
WeakReference<Resource> weakReference = new WeakReference(resource);
System.out.println("before gc");
System.out.println("resource = " + resource);
System.out.println("weakRef = " + weakReference.get());
System.out.println("after gc");
resource = null;
System.gc();
System.out.println("resource = " + resource);
System.out.println("weakRef = " + weakReference.get());
}
Run一把毫无悬念的结果
before gc
resource = team.opay.pay.Resource@484b61fc
weakRef = team.opay.pay.Resource@484b61fc
after gc
resource = null
weakRef = java.lang.ref.WeakReference@45fe3ee3
weakRef.get = null
Process finished with exit code 0
常规弱引用使用测试结论
- 弱引用包裹的对象resource返回null
- 但是弱引用本身是(WeakReference != null)
2. 扩展WeakReference
2.1 简单扩展(不使用引用队列)
class ReuseWeakReferenceI extends WeakReference<Resource> {
private String key;
private Object source;
public ReuseWeakReferenceI(String key, Resource referent) {
super(referent);
/**
* 这里为什么是Resource的data字段呢?
* 因为get方法毫无悬念的为空 可以尝试引用一下起内部的变量
*/
this.source = referent.getData();
this.key = key;
}
public Object getSource() {
return source;
}
public String getKey() {
return key;
}
public void reset() {
this.key = null;
this.source = null;// 让gc尽快回收
clear();
}
}
测试代码如下
@Test
public void testWeakSecond() {
Resource resource = new Resource("data can re-use");
ReuseWeakReferenceI weakReference = new ReuseWeakReferenceI("", resource);
System.out.println("before gc");
System.out.println("resource = " + resource);
System.out.println("weakRef = " + weakReference.get());
System.out.println("after gc");
resource = null;
System.gc();
System.out.println("resource = " + resource);
System.out.println("weakRef = " + weakReference);
System.out.println("weakRef.get = " + weakReference.get());
System.out.println("weakRef.get = " + weakReference.getSource());
}
继续Run
before gc
resource = team.opay.pay.Resource@484b61fc
weakRef = team.opay.pay.Resource@484b61fc
after gc
resource = null
weakRef = team.opay.pay.ReuseWeakReferenceI@45fe3ee3
weakRef.get = null
weakRef.data = data can re-use
2.1无引用队列测试结论
-WeakReference引用在,其内部强引用也就在
2.2 扩展(使用引用队列)
class ReuseWeakReference extends WeakReference<Resource> {
private String key;
private Object source;
public ReuseWeakReference(String key, Resource referent, ReferenceQueue<? super Resource> q) {
super(referent, q);
/**
* 这里为什么是Resource的data字段呢?
* 因为get方法毫无悬念的为空 可以尝试引用一下起内部的变量
*/
this.source = referent.getData();
this.key = key;
}
public Object getSource() {
return source;
}
public String getKey() {
return key;
}
public void reset() {
this.key = null;
this.source = null;// 让gc尽快回收
clear();
}
}
测试代码
@Test
public void testLast() {
String key = "sourceKey";
Resource resource = new Resource("data can re-use");
ReferenceQueue<Resource> referenceQueue = new ReferenceQueue<>();
ReuseWeakReference weakReference = new ReuseWeakReference(key, resource, referenceQueue);
Map<String, ReuseWeakReference> cache = new HashMap<>();
cache.put(key, weakReference);
System.out.println("before call gc");
System.out.println("resource = " + resource);
System.out.println("weakRef = " + weakReference.get());
resource = null;
System.gc();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("after call gc");
System.out.println("resource = " + resource);
System.out.println("weakRef = " + weakReference.get());
Reference reference;
while ((reference = referenceQueue.poll()) != null) {
ReuseWeakReference reuse = (ReuseWeakReference)reference;
System.out.println("weakCacheMap size(before remove) = " + cache.size());
cache.remove(reuse.getKey());
System.out.println("weakCacheMap size(after remove) = " + cache.size());
System.out.println("weakRef.queue reuse value = " + reuse.getSource());
}
}
运行结果
before call gc
resource = team.opay.pay.Resource@484b61fc
weakRef = team.opay.pay.Resource@484b61fc
after call gc
resource = null
weakRef = null
weakCacheMap size(before remove) = 1
weakCacheMap size(after remove) = 0
weakRef.queue ref.data (in memory) = data can re-use
2.2使用引用队列扩展测试结论
- (同2.1测试结论)
3. Andorid Glide实践
Glide ActiveResources之弱引用复用实践篇
当检测到正在使用的缓存不在使用时,有如下复用处理
- bitmap.recycle()
- cache.put() //memoryCache
- bitmapPool //inMutable