Cache 之自我实现内存缓存

来源:互联网 发布:淘宝贷款申请条件 编辑:程序博客网 时间:2024/05/16 09:30

自我实现cache简述

话说回来,缓存这个东东,其实真的是very nice 的东西,当然要你在使用得当,应用的很好的情况下,否则那就不妙了。

       使用第三方的cache,也好也不好,好处就是拿着API ,  做做配置 ,就直接可以使用了,性能什么的,自然有的描述;不好的地方是:什么都要遵守它的

要求,不能按照自己想要的来操作,其实也挺操蛋的。那么如何实现自己的cache呐 ?


总体来说cache 可以存放在磁盘上,也可以存放在内存中,有以下一点思路:

      1. cache 是存放在什么地方的?内存or 磁盘,有没有限制?限制的条件是什么?

       2. 如何计算放入的object 的大小,这个是个非常关键的地方,要是不知道放入的object的大小,那还怎么玩呀、是不是?

       3. cache 的管理:cache的移除,cache 的放入,cache的获取


内存计算工具类

    此类主要用来计算放入的object对象的内存的大小,就是计算一个object 的大小。

   private static final Map<Class, Integer> primitiveSizes = new IdentityHashMap<Class, Integer>() {
      {
         put(boolean.class, new Integer(1));
         put(byte.class, new Integer(1));
         put(char.class, new Integer(2));
         put(short.class, new Integer(2));
         put(int.class, new Integer(4));
         put(float.class, new Integer(4));
         put(double.class, new Integer(8));
         put(long.class, new Integer(8));
      }
   };


   public static long estimate(Object obj) {
      Map visited = new IdentityHashMap();
      Stack stack = new Stack();
      long result = _estimate(visited, stack, obj);


      while(!stack.isEmpty()) {
         result += _estimate(visited, stack, stack.pop());
      }


      visited.clear();
      return result;
   }


   private static boolean skipObject(Map visited, Stack stack, Object obj) {
      return (obj == null) || visited.containsKey(obj);
   }


   private static long _estimate(Map visited, Stack stack, Object obj) {
      if(skipObject(visited, stack, obj)) {
         return 0;
      }


      visited.put(obj, null);
      long result = 0;
      Class clazz = obj.getClass();


      if(clazz.isArray()) {
         return _estimateArray(visited, stack, obj);
      }


      while(clazz != null) {
         Field[] fields = clazz.getDeclaredFields();


         for(int i = 0; i < fields.length; i++) {
            if(!Modifier.isStatic(fields[i].getModifiers())) {
               if(fields[i].getType().isPrimitive()) {
                  result += getPrimitiveFieldSize(fields[i].getType());
               }
               else {
                  result += getPointerSize();
                  fields[i].setAccessible(true);


                  try {
                     Object toBeDone = fields[i].get(obj);


                     if(toBeDone != null) {
                        stack.add(toBeDone);
                     }
                  }
                  catch(IllegalAccessException ex) {
                     assert false;
                  }
               }
            }
         }


         clazz = clazz.getSuperclass();
      }


      result += getClassSize();
      return roundUpToNearestEightBytes(result);
   }


   private static long roundUpToNearestEightBytes(long result) {
      if((result % 8) != 0) {
         result += 8 - (result % 8);
      }


      return result;
   }


   protected static long _estimateArray(Map visited, Stack stack, Object obj) {
      long result = 16;
      int length = Array.getLength(obj);


      if(length != 0) {
         Class arrayElementClazz = obj.getClass().getComponentType();


         if(arrayElementClazz.isPrimitive()) {
            result += length * getPrimitiveArrayElementSize(arrayElementClazz);
         }
         else {
            for(int i = 0; i < length; i++) {
               result += getPointerSize()
                  + _estimate(visited, stack, Array.get(obj, i));
            }
         }
      }


      return result;
   }


   private static int getPrimitiveFieldSize(Class clazz) {
      return ((Integer) primitiveSizes.get(clazz)).intValue();
   }


   private static int getPrimitiveArrayElementSize(Class clazz) {
      return getPrimitiveFieldSize(clazz);
   }


   private static int getPointerSize() {
      return 4;
   }


   private static int getClassSize() {
      return 8;
   }     



自己memorycache的实现


这个就是本类的实现了,用此来控制内存的消耗。
public class MemoryCache {
  private static Map cache = new LinkedHashMap();
  private static long MAX = 0L;
  private static long memory = 0L;


  static {
     float ratio = 0.6f;


     try {
        String val = "0.50";//UtilEnv.getProperty("memory.cache.ratio");
        ratio = Float.parseFloat(val);
     }
     catch(Throwable t) {
        // ignore it
     }


     long xmx = 1 * 1024 * 1024 * 1024; // 1G


     try {
        xmx = Runtime.getRuntime().maxMemory();
     }
     catch(Throwable t) {
        // ignore it
     }


     MAX = (long) (xmx * ratio);
  }


  public static void put(String key, Object value) {
     long size = SizeOf.estimate(value);


     synchronized(cache) {
        remove(key);
        memory += size;
        Iterator<String> keys = new ArrayList(cache.keySet()).iterator();


        while(memory > MAX && keys.hasNext()) {
           String rkey = keys.next();
           remove(rkey);
        }


        cache.put(key, value);
     }
  }


  public static Object get(String key) {
     synchronized(cache) {
        // move to last
        Object value = cache.remove(key);


        if(value != null) {
           cache.put(key, value);
        }


        return value;
     }
  }


  public static void remove(String key) {
     synchronized(cache) {
        Object rvalue = cache.remove(key);


        if(rvalue != null) {
           long rsize = SizeOf.estimate(rvalue);
           memory -= rsize;
        }
     }
  }


}



0 0