weakreference使用,weak function
理解StrongReference,SoftReference, WeakReference的区别
Java 中一共有 4 种类型的引用 : StrongReference、 SoftReference、 WeakReference 以及 PhantomReference (传说中的幽灵引用 呵呵),
这 4 种类型的引用与 GC 有着密切的关系,? 让我们逐一来看它们的定义和使用场景 :
1. Strong Reference
StrongReference 是 Java 的默认引用实现,? 它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收
@Test?
public void strongReference() {?
Object referent =new Object();?
/**
? * 通过赋值创建 StrongReference
? ? */?
? ? Object strongReference = referent;?
? assertSame(referent, strongReference);?
referent =null;?
System.gc();?
/**
? ? * StrongReference 在 GC 后不会被回收,因为StrongReference 是用= ,强引用,如果再把strongReference=null 那将回收
? ? */?
assertNotNull(strongReference);?
}?
? 2. WeakReference WeakHashMap
WeakReference, 顾名思义,? 是一个弱引用,? 当所引用的对象在 JVM 内不再有强引用时, GC 后 weak reference 将会被自动回收
@Test?
public void weakReference() {?
Object referent =new Object();?
WeakReference weakRerference =new WeakReferenceObject(referent);?
assertSame(referent, weakRerference.get());?
referent =null;?
System.gc();?
/**
? ? * 一旦没有指向 referent 的强引用, weak reference 在 GC 后会被自动回收
? ? */?
assertNull(weakRerference.get());?
}?
WeakHashMap 使用 WeakReference 作为 key, 一旦没有指向 key 的强引用, WeakHashMap 在 GC 后将自动删除相关的 entry
@Test?
public void weakHashMap() throws InterruptedException {?
Map weakHashMap =new WeakHashMapObject, Object();?
Object key =new Object();?
Object value =new Object();?
? ? weakHashMap.put(key, value);?
? ? assertTrue(weakHashMap.containsValue(value));?
key =null;?
? System.gc();?
/**
? ? * 等待无效 entries 进入 ReferenceQueue 以便下一次调用 getTable 时被清理
? ? */?
Thread.sleep(1000);?
/**
? ? * 一旦没有指向 key 的强引用, WeakHashMap 在 GC 后将自动删除相关的 entry
? ? */?
? assertFalse(weakHashMap.containsValue(value));?
}?
3. SoftReference
SoftReference 于 WeakReference 的特性基本一致, 最大的区别在于 SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证), 这一特性使得 SoftReference 非常适合缓存应用
@Test?
public void softReference() {?
Object referent =new Object();?
SoftReference softRerference =new SoftReferenceObject(referent);?
? ? assertNotNull(softRerference.get());?
referent =null;?
? ? System.gc();?
/**
? ? *? soft references 只有在 jvm OutOfMemory 之前才会被回收, 所以它非常适合缓存应用
? ? */?
? ? assertNotNull(softRerference.get());?
}?
C#弱引用(WeakReference)
在日常开发中,通常会遇到一些大对象的处理。这些大对象通常在整个程序中多次使用。例如:大文件对象,大的字典类。通常情况下我们会使用下面的方式:
作为一个方法的内置本地变量;
作为一个类的字段存在;
这两种方式都不是很好。作为一个类的字段,类的实例将一直持有这个大对象,消耗很多内存;作为一个方法的本地变量使用,当方法执行完毕,这个大对象离开了作用域,但此时不一定会被GC直接回收。造成不必要的内存消耗。且每次调用该方法时,会重新创建新的大对象,增加程序的内存消耗。
如果创建对象很消耗资源,且我们想要避免多次创建同一个对象。可以使用类的字段方式。
通常情况下,当一个对象离开了作用域,或者被设置为null。我们将无法访问到它。.NET提供了一个 WeakReference 类,可以完美的解决这个问题。
引用:
[.NET] WeakReference的使用
WeakReference
A SoftReference should be cleared and enqueued as late as possible, that is, in case the VM is in danger of running out of memory.
一个软引用应该尽可能迟的被清理和入列,因此,在这种情况下虚拟机(VM)就存在内存溢出的风险(危险)。
个人理解:问题在“as late as possible”——始终过迟的清理垃圾,肯定就有内存溢出的风险(危险)。
------------------------------------
All objects formerly being referenced by ref become eligible for finalization.
所有先前被ref引用的对象都将符合垃圾回收(finalization)的条件。
ref:地址引用,java里就是指被new创建的对象。
除非是使用JNI,所占用的内存将不在ref的范围(Thinking in Java 4th, 120页)
何时该用WeakReference
何时该用WeakReference
答:一个例子是:当你的图片Bitmap生成通过AsynchTask 做好回来,需要用到ListView里的ImageView,而此ImageView有可能因为滚动的缘故不存在的话,针对这种情况,就要对ImageView来适用WeakReference, 适用动作在AsynchTask创建时就用WeakReference来引用ImageView 对象。
例子可见Android manual.
简单原则:对要用的对象,没有绝对控制权,需要小心使用WeakReference,确保此对象是存在的。