为了更加灵活的控制对象的生命周期,jdk1.2以后,将对象的引用分为4个级别:
一、强引用(StrongReference)
特性:当内存空间不足时,java虚拟机宁可抛出OutOfMemoryError错误,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
二、 软引用(SoftReference)
特性:除非JVM即将OutOfMemory,否则不会被GC回收。换句话说,垃圾回收器在运行时可能会(也可能不会)释放软引用对象。对象是否被释放取决于垃圾收集器的算法以及垃圾收集器运行时可用的内存数量。 实际程序设计中使用软引用的情况较多,通常用来实现内存敏感的高速缓存。
三、弱引用(WeakReference)
特性:一旦被垃圾回收器发现,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。通常用于Debug、内存监视工具等程序。
四、虚引用(PhantomReference)
特性:形同虚设,不决定对象的生命周期,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。用途较少,主要用于辅助finalize函数的使用。
软引用实现的一个map工具类实例:
package com.huang.mylottery.utils;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.HashMap;
/**
* 软引用的map集合,降低对象的引用级别——V
*
* 第一步:将占用内存较多的对象(手机),添加到软引用对象(袋子)中
* 第二步:一旦对象(手机)被GC回收了,清理软引用对象(袋子)
*
* @author wuseyukui
*
* @param <K>
* @param <V>
*/
public class SoftMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = 1L;
/**
* 垃圾Reference的队列(记录回收掉的软引用对象(袋子)的引用)
* 原来ReferenceQueue起到一个监听器的效果,当发现SoftReference.get()方法返回的是null值时,
* 就会将SoftReference注册到自己里面队列里,当我们调用ReferenceQueue的poll()方法时,返回并删除该SoftReference。
*/
private ReferenceQueue<V> queue;
/**
* 用于Chche内容的存储(存放软引用对象(袋子)的集合)
*/
private HashMap<K, MySoftReference<V>> temp;
public SoftMap() {
temp = new HashMap<K, MySoftReference<V>>();
queue = new ReferenceQueue<V>();
}
@Override
public V put(K key, V value) {
// 将对象(手机)装入软引用对象(袋子)
MySoftReference<V> sr = new MySoftReference<V>(key, value, queue);
temp.put(key, sr);
return null;
}
@Override
public boolean containsKey(Object key) {
return get(key) != null;
}
@Override
public V get(Object key) {
clearSR();
MySoftReference<V> sr = temp.get(key);
if (sr != null) {
return sr.get();
}
return null;
}
/**
* 清理 软引用对象
* @author wuseyukui
*
*/
@SuppressWarnings("unchecked")
private void clearSR() {
if (temp.size() > 0) {
MySoftReference<V> reference = (MySoftReference<V>) queue.poll();
while (reference != null) {
System.out.println("remove reference key:"+reference.key);
temp.remove(reference.key);
// 当我们调用它的poll()方法的时候,如果这个队列中不是空队列,那么将返回队列前面的那个Reference对象。
// 在任何时候,我们都可以调用ReferenceQueue的poll()方法来检查是否有它所关心的非强可及对象被回收。
// 如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。
// 利用这个方法,我们可以检查哪个SoftReference所软引用的对象已经被回收。
// 于是我们可以把这些失去所软引用的对象的SoftReference对象清除掉。
reference = (MySoftReference<V>)queue.poll();
}
}
}
/**
* 增强版的(袋子),方便清理操作
* @author wuseyukui
*
* @param <V>
*/
@SuppressWarnings("hiding")
private class MySoftReference<V> extends SoftReference<V> {
private Object key;
public MySoftReference(K key, V r, ReferenceQueue<? super V> q) {
super(r, q);
this.key = key;
}
}
}