西安网站建设开发熊掌号,成都企业网站seo技术,南京城乡建设局网站,建正建设官方网站1.背景
在项目中#xff0c;如果频繁的通过new 创建对象#xff0c;之后让gc再去回收#xff0c;这就很容易造成内存抖动#xff0c;并且频繁的GC本身也会消耗内存#xff0c;这样就很容易在一瞬间造成OOM 内存溢出#xff0c;因为瞬间申请大量内存会造成内存占用突然升…1.背景
在项目中如果频繁的通过new 创建对象之后让gc再去回收这就很容易造成内存抖动并且频繁的GC本身也会消耗内存这样就很容易在一瞬间造成OOM 内存溢出因为瞬间申请大量内存会造成内存占用突然升高如果GC 还没来的及回收或者频繁GC,内存就会居高不下这时有两种处理方式一个是减少对象的创建一个是复用对象。
2. 对象复用的基本原理
所谓对象复用就是在对象创建使用完成后将对象内部的数据清除然后将对象放到缓存中等到下次需要创建新对象时拿出来复用这样一来一回只需要占用固定的内存就可以不用每次都去new 一个对象申请内存即避免的内存抖动又避免了频繁GC,造成可能的稳定性问题但是也有一个小弊端就是这块缓存的对象所占的对象是固定的无法随着GC来回收如果需要回收需要我们手动处理所以这个就需要我们对使用场景来评估。
3.如何构建一个对象池
1.需要有一个合适的对象 2.定一个对象池的大小 3.处理对象的回收 4.在核实的位置获取对象池中数据并且在使用完成后回收
4. 构建一个对象池
public class MapCache extends HashMapString, String {private static final String TAG MapCache;//下一条对象MapCache next;public static final Object sPoolSync new Object ();// 链表首个对象private static MapCache sPool;//当前链表个数private static int sPoolSize 0;//可缓存的最大空闲对象数量超出后将开始new 对象由GC 处理回收private static final int MAX_POOL_SIZE 50;Overridepublic void clear() {recycle ();}/*** 获取map对像如果对象池存在空闲对象就从头部取出一个空对象返回* 否则new 一个新对象。*/public static MapCache obtain() {synchronized (sPoolSync) {if (sPool ! null) {MapCache m sPool;sPool m.next;m.next null;sPoolSize--;// 返回链表头部对象return m;}}return new MapCache ();}/*** 回收对象资源*/private void recycle() {super.clear ();synchronized (sPoolSync) {if (sPoolSize MAX_POOL_SIZE) {next sPool;// 将当前消息放到链表头部sPool this;//链表消息池对象增加1sPoolSize;}}}public static MapCache createCacheMap(MapString, String args) {MapCache map obtain ();for (Map.Entry?, ? entry : args.entrySet ()) {String key (String) entry.getKey ();if (key null) {Log.e (TAG, CreateMap error: key null);continue;}map.put (key, (String) entry.getValue ());}return map;}private static boolean isMapCache(Map mapCache) {if (mapCache instanceof MapCache) {return true;}return false;}public static MapCache createMap(Map mapCache) {if (mapCachenull || mapCache.size ()0) {return null;}if (isMapCache(mapCache)) {return (MapCache) mapCache;}return createCacheMap (mapCache);}}其实还算简单基本原理就是定一个对象池大小用一个链表来存储对象然后定义一个静态的头部对象sPoolSync然后定义这个头部对象的next 指向的下一个对象这样就形成了一个链表的对象池。
3.1 获取对象
当通过obtain() 方法来获取一个对象时如果链表中有缓存的对象数据就取出链表首部的对象然后将他的下一个对象指向头部对象然后将对象池减一个如果没有足够的对象或者首次调用那就new 一个对象返回。
3.2 对象的回收
对象内容的回收recycle()需要根据不同的对象定义来处理就比如我这定义的HashMap,使用完成后只需要调用clear 方法将原数据清空然后将这个对象加入到线程池中即可。 具体操作 就是先将当前的链表头部对象指向当前的空闲对像的next然后将空闲该对象 指向头部静态对像然后对象池加一这样就顺利将空闲对像加到链表头部。