程序优化
一、对象的引用级别: ①强引用:对象创建,默认是强引用,宁愿抛出OOM异常,GC也不会清理强引用。如Object obj = new Object(); ②软引用:SoftwareReference,在发生OOM异常之前,GC将清理所有的软引用 ③弱引用: WeakReference ,GC在清理时,发现有弱引用,就会将其清理掉 ④虚引用: PhantomReference,一创建,就会被清理掉 |
软引用:java.lang.ref.SoftReference<T> 软可到达对象的所有软引用都要保证在虚拟机抛出 OutOfMemoryError 之前已经被清除。应用场景: ①申请内存速度不是过快(如ListView中item访问网络来获取图片展示)
②GridView 10张图片,但如果快速的滚动界面,那么GC来不及回收,会出现OOM异常 |
问题: 在UIManager中,维护着一个Map,该Map保存着所有的界面, 如果只有几个界面,还可以顶住,一般一个界面占用150K左右的内存,如果当存了100个Map后,那么内存将占用10M多,此时就无法在低内存下运行程序了,会出现OOM异常。 private Map<String, BaseView> views = new HashMap<String, BaseView>(); 解决:这时就不能用强引用了,因为强引用在GC回收内存时,就算出现OOM异常,也不会回收强引用 那么用软引用SoftwareReference来 代码: private static Map<String, BaseView> views;
static {
if (isHighMem()) {// 内存充足可用,直接用强引用
views = new HashMap<String, BaseView>();
} else {// 内存紧缺
views = new MyReferenceMap<String, BaseView>();
}
}package cn.zengfansheng.lottery.view.manager;
import java.lang.ref.SoftReference;
import java.util.HashMap;
/**
* 软引用的集合
*
* @param <K>
* @param <V>
*/
public class MyReferenceMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = 1L;
// note********************* *********************
// 内存不足:GC会回收内存(对象的应用级别:1.2-------强引用、软引用、弱引用、虚引用),强引用对象宁愿抛出OOM异常,也不会清理
// 降低引用级别
private HashMap<K, SoftReference<V>> hashMapSR;
// 将V给软引用
public MyReferenceMap() {
// Object obj = new Object();// 强引用(相当于手拿着一个手机)
// 降低引用级别(将其装入一个袋子中)
// SoftReference<Object> sr = new SoftReference<Object>(obj);// 本身是一个强引用
// 相当于一个袋子,将obj(手机)装入袋子中去
hashMapSR = new HashMap<K, SoftReference<V>>();
}
// put到集合中去(1、首先将其用一个软引用对象给引用起来 2、加入到集合中去)
@Override
public V put(K key, V value) {
// 将传递进来的V,用一个软引用给引用起来
SoftReference<V> sr = new SoftReference<V>(value);// 降低引用级别到软引用
hashMapSR.put(key, sr);
value = null;
// 现在value是一个软可达到的对象
return value;
}
// 从集合中get出来(1、首先将key到map中去取,2、取出的是软引用对象,3、再从该软引用对象中取出,如果为null说明被回收了)
@Override
public V get(Object key) {
SoftReference<V> sr = hashMapSR.get(key);// 获取到“袋子”
V v = sr.get();// 如果没有被清理掉,那么返回该key的引用;否则被清理了,返回null
return v;
}
@Override
public boolean containsKey(Object key) {
SoftReference<V> sr = hashMapSR.get(key);// 获取到“袋子”
return sr.get() == null;// 如果被GC回收掉false
}
// 还需要出什么方法?
// map中需要使用什么方法,那么就在这里将其复写掉
}
|
核心代码: package cn.zengfansheng.lottery.view.manager;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.HashMap;
/**
* 软引用的集合
*
* @param <K>
* @param <V>
*/
public class MyReferenceMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = 1L;
// note*********************1、软引用*********************
// 内存不足:GC会回收内存(对象的应用级别:1.2-------强引用、软引用、弱引用、虚引用),强引用对象宁愿抛出OOM异常,也不会清理
// 降低引用级别
private HashMap<K, SoftReference<V>> hashMapSR;
private ReferenceQueue<V> q;// 放置被回收掉手机的“袋子”的引用
// 将V给软引用
public MyReferenceMap() {
// Object obj = new Object();// 强引用(相当于手拿着一个手机)
// 降低引用级别(将其装入一个袋子中)
// SoftReference<Object> sr = new SoftReference<Object>(obj);// 本身是一个强引用
// 相当于一个袋子,将obj(手机)装入袋子中去
hashMapSR = new HashMap<K, SoftReference<V>>();
q = new ReferenceQueue<V>();// q一个队列,它会将每一个引用的对象,保存一个引用在里面
}
// put到集合中去(1、首先将其用一个软引用对象给引用起来 2、加入到集合中去)
@Override
public V put(K key, V value) {
// SoftReference<V> sr = new SoftReference<V>(value, q);// 降低引用级别到软引用
MySoftwareReference<K, V> sr = new MySoftwareReference<K, V>(key, value, q);
hashMapSR.put(key, sr);
value = null;
// 现在value是一个软可达到的对象
return value;
}
// 从集合中get出来(1、首先将key到map中去取,2、取出的是软引用对象,3、再从该软引用对象中取出,如果为null说明被回收了)
@Override
public V get(Object key) {
SoftReference<V> sr = hashMapSR.get(key);// 获取到“袋子”
V v = sr.get();// 如果没有被清理掉,那么返回该key的引用;否则被清理了,返回null
return v;
}
@Override
public boolean containsKey(Object key) {
clearSRValue();
SoftReference<V> sr = hashMapSR.get(key);// 获取到“袋子”
if (sr != null) {// 说明软引用中有值,也就是有引用
return true;
// return sr.get() == null;// 如果被GC回收掉false
} else {// 为null,说明没有引用了
return false;
}
}
// 还需要出什么方法?
// map中需要使用什么方法,那么就在这里将其复写掉
// note*********************2、软引用对象集合在被清空时,将其移除掉*********************
// 当袋子内的手机已经被回收掉,清理掉强引用的袋子
/**
* 清理没有用的袋子
*/
public void clearSRValue(){
MySoftwareReference<K, V> sr = (MySoftwareReference<K, V>) q.poll();
while (sr != null) {
// /hashMapSR.remove(key);//由于要将其从map清除,所以需要一个key,但系统的Reference没有key,所以我们需要自定义,来增强
// 从hashMapSR将sr清除
hashMapSR.remove(sr.key);
sr = (MySoftwareReference<K, V>) q.poll();
}
}
/**
* 自定义的SoftwareReference,增加一个key,用来在乱引用对象被GC回收时,将该软引用也给移除掉
*
* @author hacket
*
* @param <K>
* @param <V>
*/
private class MySoftwareReference<K, V> extends SoftReference<V> {
Object key = null;
public MySoftwareReference(K key, V value, ReferenceQueue<? super V> q) {
super(value, q);
this.key = key;
}
}
} |
|
|