Java资源缓存 之 LruCache_java

例如对 网络加载图片进行缓存 :

  // 得到 应用程序 被分配的最大的内存
    int maxMemory=(int) Runtime.getRuntime().maxMemory();
    // 取处内存的 1/5 用来当 缓存 大小
    int cachSize=maxMemory/5;
    // 实例化 LruCache
    lruCache=new lruCache<String, Bitmap>(cachSize){
      //内部方法sizeOf设置每一张图片的缓存大小
      protected int sizeOf(String key, Bitmap value) {
        //在每次存入缓存时调用,告诉系统这张缓存图片有多大
        // 相当于 为每次 要缓存的 资源 分配 大小空间
        return value.getByteCount();
      }
    };

上面的 代码 一般 放在初始化的 方法 里面

其实 可以将 LurCache 类 理解 为 Map 类 map 有 put和 get 方法

接下去就调用put 和 get 方法 进行需要缓存资源的存取

LurCache 的 add :

public void putBitmapToCache(String url,Bitmap bitmap){
    if (getBitmapfromCache(url)==null) {//判断当前缓存是否存在
      lruCache.put(url, bitmap);
    }
  }
LurCache 的 get:

public Bitmap getBitmapfromCache(String url){
    return lruCache.get(url);//可将lruCache看成map
  }

调用上面的 add 和 get 方法 就可以对资源进行缓存的 ,还是挺简单的,

但要注意一点 LruCache lruCache=new LruCache<String, Bitmap>(cachSize) 只能被new 一次 ,不然不同对象就不同的缓存了

附上Android的Lrucache类

package android.util; 

import java.util.LinkedHashMap;
import java.util.Map; 

/**
 * A cache that holds strong references to a limited number of values. Each time
 * a value is accessed, it is moved to the head of a queue. When a value is
 * added to a full cache, the value at the end of that queue is evicted and may
 * become eligible for garbage collection.
 * Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部。
 * 当cache已满的时候加入新的item时,在队列尾部的item会被回收。
 * <p>If your cached values hold resources that need to be explicitly released,
 * override {@link #entryRemoved}.
 * 如果你cache的某个值需要明确释放,重写entryRemoved()
 * <p>If a cache miss should be computed on demand for the corresponding keys,
 * override {@link #create}. This simplifies the calling code, allowing it to
 * assume a value will always be returned, even when there's a cache miss.
 * 如果key相对应的item丢掉啦,重写create().这简化了调用代码,即使丢失了也总会返回。
 * <p>By default, the cache size is measured in the number of entries. Override
 * {@link #sizeOf} to size the cache in different units. For example, this cache
 * is limited to 4MiB of bitmaps: 默认cache大小是测量的item的数量,重写sizeof计算不同item的
 * 大小。
 * <pre>  {@code
 *  int cacheSize = 4 * 1024 * 1024; // 4MiB
 *  LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
 *    protected int sizeOf(String key, Bitmap value) {
 *      return value.getByteCount();
 *    }
 *  }}</pre>
 *
 * <p>This class is thread-safe. Perform multiple cache operations atomically by
 * synchronizing on the cache: <pre>  {@code
 *  synchronized (cache) {
 *   if (cache.get(key) == null) {
 *     cache.put(key, value);
 *   }
 *  }}</pre>
 *
 * <p>This class does not allow null to be used as a key or value. A return
 * value of null from {@link #get}, {@link #put} or {@link #remove} is
 * unambiguous: the key was not in the cache.
 * 不允许key或者value为null
 * 当get(),put(),remove()返回值为null时,key相应的项不在cache中
 */
public class LruCache<K, V> {
  private final LinkedHashMap<K, V> map; 

  /** Size of this cache in units. Not necessarily the number of elements. */
  private int size; //已经存储的大小
  private int maxSize; //规定的最大存储空间

  private int putCount; //put的次数
  private int createCount; //create的次数
  private int evictionCount; //回收的次数
  private int hitCount; //命中的次数
  private int missCount; //丢失的次数

  /**
   * @param maxSize for caches that do not override {@link #sizeOf}, this is
   *   the maximum number of entries in the cache. For all other caches,
   *   this is the maximum sum of the sizes of the entries in this cache.
   */
  public LruCache(int maxSize) {
    if (maxSize <= 0) {
      throw new IllegalArgumentException("maxSize <= 0");
    }
    this.maxSize = maxSize;
    this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
  } 

  /**
   * Returns the value for {@code key} if it exists in the cache or can be
   * created by {@code #create}. If a value was returned, it is moved to the
   * head of the queue. This returns null if a value is not cached and cannot
   * be created. 通过key返回相应的item,或者创建返回相应的item。相应的item会移动到队列的头部,
   * 如果item的value没有被cache或者不能被创建,则返回null。
   */
  public final V get(K key) {
    if (key == null) {
      throw new NullPointerException("key == null");
    } 

    V mapValue;
    synchronized (this) {
      mapValue = map.get(key);
      if (mapValue != null) {
        hitCount++; //命中
        return mapValue;
      }
      missCount++; //丢失
    } 

    /*
     * Attempt to create a value. This may take a long time, and the map
     * may be different when create() returns. If a conflicting value was
     * added to the map while create() was working, we leave that value in
     * the map and release the created value.
     * 如果丢失了就试图创建一个item
     */ 

    V createdValue = create(key);
    if (createdValue == null) {
      return null;
    } 

    synchronized (this) {
      createCount++;//创建++
      mapValue = map.put(key, createdValue); 

      if (mapValue != null) {
        // There was a conflict so undo that last put
        //如果前面存在oldValue,那么撤销put()
        map.put(key, mapValue);
      } else {
        size += safeSizeOf(key, createdValue);
      }
    } 

    if (mapValue != null) {
      entryRemoved(false, key, createdValue, mapValue);
      return mapValue;
    } else {
      trimToSize(maxSize);
      return createdValue;
    }
  } 

  /**
   * Caches {@code value} for {@code key}. The value is moved to the head of
   * the queue.
   *
   * @return the previous value mapped by {@code key}.
   */
  public final V put(K key, V value) {
    if (key == null || value == null) {
      throw new NullPointerException("key == null || value == null");
    } 

    V previous;
    synchronized (this) {
      putCount++;
      size += safeSizeOf(key, value);
      previous = map.put(key, value);
      if (previous != null) { //返回的先前的value值
        size -= safeSizeOf(key, previous);
      }
    } 

    if (previous != null) {
      entryRemoved(false, key, previous, value);
    } 

    trimToSize(maxSize);
    return previous;
  } 

  /**
   * @param maxSize the maximum size of the cache before returning. May be -1
   *   to evict even 0-sized elements.
   * 清空cache空间
   */
  private void trimToSize(int maxSize) {
    while (true) {
      K key;
      V value;
      synchronized (this) {
        if (size < 0 || (map.isEmpty() && size != 0)) {
          throw new IllegalStateException(getClass().getName()
              + ".sizeOf() is reporting inconsistent results!");
        } 

        if (size <= maxSize) {
          break;
        } 

        Map.Entry<K, V> toEvict = map.eldest();
        if (toEvict == null) {
          break;
        } 

        key = toEvict.getKey();
        value = toEvict.getValue();
        map.remove(key);
        size -= safeSizeOf(key, value);
        evictionCount++;
      } 

      entryRemoved(true, key, value, null);
    }
  } 

  /**
   * Removes the entry for {@code key} if it exists.
   * 删除key相应的cache项,返回相应的value
   * @return the previous value mapped by {@code key}.
   */
  public final V remove(K key) {
    if (key == null) {
      throw new NullPointerException("key == null");
    } 

    V previous;
    synchronized (this) {
      previous = map.remove(key);
      if (previous != null) {
        size -= safeSizeOf(key, previous);
      }
    } 

    if (previous != null) {
      entryRemoved(false, key, previous, null);
    } 

    return previous;
  } 

  /**
   * Called for entries that have been evicted or removed. This method is
   * invoked when a value is evicted to make space, removed by a call to
   * {@link #remove}, or replaced by a call to {@link #put}. The default
   * implementation does nothing.
   * 当item被回收或者删掉时调用。改方法当value被回收释放存储空间时被remove调用,
   * 或者替换item值时put调用,默认实现什么都没做。
   * <p>The method is called without synchronization: other threads may
   * access the cache while this method is executing.
   *
   * @param evicted true if the entry is being removed to make space, false
   *   if the removal was caused by a {@link #put} or {@link #remove}.
   * true---为释放空间被删除;false---put或remove导致
   * @param newValue the new value for {@code key}, if it exists. If non-null,
   *   this removal was caused by a {@link #put}. Otherwise it was caused by
   *   an eviction or a {@link #remove}.
   */
  protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} 

  /**
   * Called after a cache miss to compute a value for the corresponding key.
   * Returns the computed value or null if no value can be computed. The
   * default implementation returns null.
   * 当某Item丢失时会调用到,返回计算的相应的value或者null
   * <p>The method is called without synchronization: other threads may
   * access the cache while this method is executing.
   *
   * <p>If a value for {@code key} exists in the cache when this method
   * returns, the created value will be released with {@link #entryRemoved}
   * and discarded. This can occur when multiple threads request the same key
   * at the same time (causing multiple values to be created), or when one
   * thread calls {@link #put} while another is creating a value for the same
   * key.
   */
  protected V create(K key) {
    return null;
  } 

  private int safeSizeOf(K key, V value) {
    int result = sizeOf(key, value);
    if (result < 0) {
      throw new IllegalStateException("Negative size: " + key + "=" + value);
    }
    return result;
  } 

  /**
   * Returns the size of the entry for {@code key} and {@code value} in
   * user-defined units. The default implementation returns 1 so that size
   * is the number of entries and max size is the maximum number of entries.
   * 返回用户定义的item的大小,默认返回1代表item的数量,最大size就是最大item值
   * <p>An entry's size must not change while it is in the cache.
   */
  protected int sizeOf(K key, V value) {
    return 1;
  } 

  /**
   * Clear the cache, calling {@link #entryRemoved} on each removed entry.
   * 清空cacke
   */
  public final void evictAll() {
    trimToSize(-1); // -1 will evict 0-sized elements
  } 

  /**
   * For caches that do not override {@link #sizeOf}, this returns the number
   * of entries in the cache. For all other caches, this returns the sum of
   * the sizes of the entries in this cache.
   */
  public synchronized final int size() {
    return size;
  } 

  /**
   * For caches that do not override {@link #sizeOf}, this returns the maximum
   * number of entries in the cache. For all other caches, this returns the
   * maximum sum of the sizes of the entries in this cache.
   */
  public synchronized final int maxSize() {
    return maxSize;
  } 

  /**
   * Returns the number of times {@link #get} returned a value that was
   * already present in the cache.
   */
  public synchronized final int hitCount() {
    return hitCount;
  } 

  /**
   * Returns the number of times {@link #get} returned null or required a new
   * value to be created.
   */
  public synchronized final int missCount() {
    return missCount;
  } 

  /**
   * Returns the number of times {@link #create(Object)} returned a value.
   */
  public synchronized final int createCount() {
    return createCount;
  } 

  /**
   * Returns the number of times {@link #put} was called.
   */
  public synchronized final int putCount() {
    return putCount;
  } 

  /**
   * Returns the number of values that have been evicted.
   * 返回被回收的数量
   */
  public synchronized final int evictionCount() {
    return evictionCount;
  } 

  /**
   * Returns a copy of the current contents of the cache, ordered from least
   * recently accessed to most recently accessed. 返回当前cache的副本,从最近最少访问到最多访问
   */
  public synchronized final Map<K, V> snapshot() {
    return new LinkedHashMap<K, V>(map);
  } 

  @Override public synchronized final String toString() {
    int accesses = hitCount + missCount;
    int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;
    return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",
        maxSize, hitCount, missCount, hitPercent);
  }
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, LRUCache
, lrucache原理
lrucache使用
lrucache清空缓存、lrucache缓存、lrucache缓存图片、android lrucache缓存、java lrucache,以便于您获取更多的相关知识。

时间: 2024-09-13 21:53:41

Java资源缓存 之 LruCache_java的相关文章

Java资源大全中文版(Awesome最新版)

目录 业务流程管理套件 字节码操作 集群管理 代码分析 编译器生成工具 构建工具 外部配置工具 约束满足问题求解程序 持续集成 CSV解析 数据库 数据结构 时间日期工具库 依赖注入 开发流程增强工具 分布式应用 分布式数据库 发布 文档处理工具 函数式编程 游戏开发 GUI 高性能计算 IDE 图像处理 JSON JVM与JDK 基于JVM的语言 日志 机器学习 消息传递 杂项 应用监控工具 原生开发库 自然语言处理 网络 ORM PDF 性能分析 响应式开发库 REST框架 科学计算与分析

JAVA 开源缓存框架

  JBossCache/TreeCache  JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能.缓存数据被自动复制,让你轻松进行Jboss服务器之间的集群工作.JBossCache能够通过Jboss应用服务或其他J2EE容器来运行一个Mbean服务,当然,它也能独立运行. JBossCache包括两个模块:TreeCache和TreeCacheAOP. TreeCache --是一个树形结构复制的事务处理缓存. TreeCacheAOP --是一个"面向

Java开源缓存系统的介绍

缓存 几种java开源缓存系统的性能比较: 以下是几个著名java开源缓存系统的介绍: OSCacheOSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案.OSCache有以下特点:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存.拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性.永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive

Java日志缓存机制的实现

概述 日志技术为产品的质量和服务提供了重要的支撑.JDK 在 1.4 版本以后加入了日志机制,为 Java 开发人员提供了便利.但这种日志机制是基于静态日志级别的,也就是在程序运行前就需设定下来要打 印的日志级别,这样就会带来一些不便. 在 JDK 提供的日志功能中,日志级别被细化为 9 级,用以 区分不同日志的用途,用来记录一个错误,或者记录正常运行的信息,又或是记录详细的调试信息.由于日志 级别是静态的,如果日志级别设定过高,低级别的日志难以打印出来,从而导致在错误发生时候,难以去追踪 错误

通过HTTP加载Java资源包

使用资源包的另一个方法 请设想一下这种情况:您必须提供一个显示小部件,它能够从数据库中提取消息键(keys)和消息替代参数,在 Java 资源包中查找键,然后格式化消息并显示出来.惟一的问题是这个资源包位于 Web 应用程序中,而不是您的小部件所在的位置.事实上,Web 应用程序位于不同的服务器中. 这并不是 Java 资源包的典型使用情况,而可能是一场噩梦.您如何来实现这一点呢?为了不进行空泛的解释,本文包括了一个示例应用程序,供你下载运行.它将更轻松地向您演示并帮助您做到这点. 示例应用程序

更新-最近学习java的缓存机制,请大家看看我的代码有什么不足

问题描述 最近学习java的缓存机制,请大家看看我的代码有什么不足 一个简单的测试类,如果在高并发下会有问题么 package com.test.cache;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;public class CacheManager { private volatile static CacheManager cacheManager;//缓存类的实例 private long upDa

java后台缓存对象的问题

问题描述 java后台缓存对象的问题 现在有这样一个场景,业务层调用远程webservice获取的结果传输到前台但只需要显示几个关键字段,待用户查询完毕后点击提交这些结果全部数据都要保存,在后台如何缓存这个查询结果?有用过在业务层增加一个属性来保存这个查询结果但是感觉不是太好,大家一般是怎么做的讨论一下,小弟在这里先谢谢啦. 解决方案 用Ehcache啊,查询完了放进Ehcache. 需要用了去Ehcache中去,类似于Map 解决方案二: 不需要缓存查询结果,只要有主键匹配上就可以了.

基于java语音缓存系统的研究与设计,怎么写毕业论文???是否需要做一个系统

问题描述 基于java语音缓存系统的研究与设计,怎么写毕业论文???是否需要做一个系统 这个东西是什么>??是否需要做出一系统,这个论文怎么写,谁帮写好能通过重谢 解决方案 这个应该是不需要做一个系统的,这并不是一个项目或者安卓的app,并不是偏向实践方向的,而是更偏向理论放心吧.个人理解,具体的建议你问问你的导师吧 解决方案二: 如果你什么都不会,那就胡乱抄抄类似的文章吧google总会用吧.http://www.docin.com/p-65599058.html 解决方案三: butaiqi

spring mvc-redis与java实现缓存查询,log日志

问题描述 redis与java实现缓存查询,log日志 我现在开发遇到两个难点,大伙给我个思路.....1.用户要求保存数据更新日志,要求有数据原值,跟修改后的值.我倒是想到几个办法,但是感觉太麻烦,有没有简略的.2.redis缓存,用户查询的数据要用redis存起来,这样的话查询条件怎么处理,我不能一个查询条件就保存一条结果缓存吧.redis对数据操作能做到根据条件吗?注:我们的开发框架是springmvc+mybaits. 解决方案 直接存库再根据用户ID或者时间分表,只是插入和查询的话,性