缓存是在web开发中经常用到的,将程序经常使用到或调用到的对象存在内存中,或者是耗时较长但又不具有实时性的查询数据放入内存中,在一定程度上可以提高性能和效率。下面我实现了一个简单的缓存,步骤如下。

创建缓存对象EntityCache.java

public class EntityCache {
  /**
   * 保存的数据
   */
  private Object datas;
 
  /**
   * 设置数据失效时间,为0表示永不失效
   */
  private long timeOut;
 
  /**
   * 最后刷新时间
   */
  private long lastRefeshTime;
 
  public EntityCache(Object datas, long timeOut, long lastRefeshTime) {
    this.datas = datas;
    this.timeOut = timeOut;
    this.lastRefeshTime = lastRefeshTime;
  }
  public Object getDatas() {
    return datas;
  }
  public void setDatas(Object datas) {
    this.datas = datas;
  }
  public long getTimeOut() {
    return timeOut;
  }
  public void setTimeOut(long timeOut) {
    this.timeOut = timeOut;
  }
  public long getLastRefeshTime() {
    return lastRefeshTime;
  }
  public void setLastRefeshTime(long lastRefeshTime) {
    this.lastRefeshTime = lastRefeshTime;
  }
 
 
}
定义缓存操作接口,ICacheManager.java
public interface ICacheManager {
  /**
   * 存入缓存
   * @param key
   * @param cache
   */
  void putCache(String key, EntityCache cache);
 
  /**
   * 存入缓存
   * @param key
   * @param cache
   */
  void putCache(String key, Object datas, long timeOut);
 
  /**
   * 获取对应缓存
   * @param key
   * @return
   */
  EntityCache getCacheByKey(String key);
 
  /**
   * 获取对应缓存
   * @param key
   * @return
   */
  Object getCacheDataByKey(String key);
 
  /**
   * 获取所有缓存
   * @param key
   * @return
   */
  Map<String, EntityCache> getCacheAll();
 
  /**
   * 判断是否在缓存中
   * @param key
   * @return
   */
  boolean isContains(String key);
 
  /**
   * 清除所有缓存
   */
  void clearAll();
 
  /**
   * 清除对应缓存
   * @param key
   */
  void clearByKey(String key);
 
  /**
   * 缓存是否超时失效
   * @param key
   * @return
   */
  boolean isTimeOut(String key);
 
  /**
   * 获取所有key
   * @return
   */
  Set<String> getAllKeys();
}

实现接口ICacheManager,CacheManagerImpl.java

这里我使用了ConcurrentHashMap来保存缓存,本来以为这样就是线程安全的,其实不然,在后面的测试中会发现它并不是线程安全的。

public class CacheManagerImpl implements ICacheManager {
  private static Map<String, EntityCache> caches = new ConcurrentHashMap<String, EntityCache>();
 
  /**
   * 存入缓存
   * @param key
   * @param cache
   */
  public void putCache(String key, EntityCache cache) {
    caches.put(key, cache);
  }
 
  /**
   * 存入缓存
   * @param key
   * @param cache
   */
  public void putCache(String key, Object datas, long timeOut) {
    timeOut = timeOut > 0 ? timeOut : 0L;
    putCache(key, new EntityCache(datas, timeOut, System.currentTimeMillis()));
  }
 
  /**
   * 获取对应缓存
   * @param key
   * @return
   */
  public EntityCache getCacheByKey(String key) {
    if (this.isContains(key)) {
      return caches.get(key);
    }
    return null;
  }
 
  /**
   * 获取对应缓存
   * @param key
   * @return
   */
  public Object getCacheDataByKey(String key) {
    if (this.isContains(key)) {
      return caches.get(key).getDatas();
    }
    return null;
  }
 
  /**
   * 获取所有缓存
   * @param key
   * @return
   */
  public Map<String, EntityCache> getCacheAll() {
    return caches;
  }
 
  /**
   * 判断是否在缓存中
   * @param key
   * @return
   */
  public boolean isContains(String key) {
    return caches.containsKey(key);
  }
 
  /**
   * 清除所有缓存
   */
  public void clearAll() {
    caches.clear();
  }
 
  /**
   * 清除对应缓存
   * @param key
   */
  public void clearByKey(String key) {
    if (this.isContains(key)) {
      caches.remove(key);
    }
  }
 
  /**
   * 缓存是否超时失效
   * @param key
   * @return
   */
  public boolean isTimeOut(String key) {
    if (!caches.containsKey(key)) {
      return true;
    }
    EntityCache cache = caches.get(key);
    long timeOut = cache.getTimeOut();
    long lastRefreshTime = cache.getLastRefeshTime();
    if (timeOut == 0 || System.currentTimeMillis() - lastRefreshTime >= timeOut) {
      return true;
    }
    return false;
  }
 
  /**
   * 获取所有key
   * @return
   */
  public Set<String> getAllKeys() {
    return caches.keySet();
  }
}
CacheListener.java,监听失效数据并移除。
public class CacheListener{
  Logger logger = Logger.getLogger("cacheLog");
  private CacheManagerImpl cacheManagerImpl;
  public CacheListener(CacheManagerImpl cacheManagerImpl) {
    this.cacheManagerImpl = cacheManagerImpl;
  }
 
  public void startListen() {
    new Thread(){
      public void run() {
        while (true) {
          for(String key : cacheManagerImpl.getAllKeys()) {
            if (cacheManagerImpl.isTimeOut(key)) {
             cacheManagerImpl.clearByKey(key);
             logger.info(key + "缓存被清除");
           }
          }
        }
      }
    }.start();
 
  }
}
测试类TestCache.java
public class TestCache {
  Logger logger = Logger.getLogger("cacheLog");
  /**
   * 测试缓存和缓存失效
   */
  @Test
  public void testCacheManager() {
    CacheManagerImpl cacheManagerImpl = new CacheManagerImpl();
    cacheManagerImpl.putCache("test", "test", 10 * 1000L);
    cacheManagerImpl.putCache("myTest", "myTest", 15 * 1000L);
    CacheListener cacheListener = new CacheListener(cacheManagerImpl);
    cacheListener.startListen();
    logger.info("test:" + cacheManagerImpl.getCacheByKey("test").getDatas());
    logger.info("myTest:" + cacheManagerImpl.getCacheByKey("myTest").getDatas());
    try {
      TimeUnit.SECONDS.sleep(20);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    logger.info("test:" + cacheManagerImpl.getCacheByKey("test"));
    logger.info("myTest:" + cacheManagerImpl.getCacheByKey("myTest"));
  }
 
  /**
   * 测试线程安全
   */
  @Test
  public void testThredSafe() {
    final String key = "thread";
    final CacheManagerImpl cacheManagerImpl = new CacheManagerImpl();
    ExecutorService exec = Executors.newCachedThreadPool();
    for (int i = 0; i < 100; i++) {
      exec.execute(new Runnable() {
        public void run() {
            if (!cacheManagerImpl.isContains(key)) {
              cacheManagerImpl.putCache(key, 1, 0);
            } else {
              //因为+1和赋值操作不是原子性的,所以把它用synchronize块包起来
              synchronized (cacheManagerImpl) {
                int value = (Integer) cacheManagerImpl.getCacheDataByKey(key) + 1;
                cacheManagerImpl.putCache(key,value , 0);
              }
            }
        }
      });
    }
    exec.shutdown();
    try {
      exec.awaitTermination(1, TimeUnit.DAYS);
    } catch (InterruptedException e1) {
      e1.printStackTrace();
    }
 
    logger.info(cacheManagerImpl.getCacheDataByKey(key).toString());
  }
}
 
 
来源:http://www.jb51.net/article/111518.htm

Java实现一个简单的缓存方法的更多相关文章

  1. 哪种缓存效果高?开源一个简单的缓存组件j2cache

    背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...

  2. 使用Java编写一个简单的Web的监控系统cpu利用率,cpu温度,总内存大小

    原文:http://www.jb51.net/article/75002.htm 这篇文章主要介绍了使用Java编写一个简单的Web的监控系统的例子,并且将重要信息转为XML通过网页前端显示,非常之实 ...

  3. Java实现一个简单的文件上传案例

    Java实现一个简单的文件上传案例 实现流程: 1.客户端从硬盘读取文件数据到程序中 2.客户端输出流,写出文件到服务端 3.服务端输出流,读取文件数据到服务端中 4.输出流,写出文件数据到服务器硬盘 ...

  4. 只是一个用EF写的一个简单的分页方法而已

    只是一个用EF写的一个简单的分页方法而已 慢慢的写吧.比如,第一步,先把所有数据查询出来吧. //第一步. public IQueryable<UserInfo> LoadPagesFor ...

  5. 使用 java 实现一个简单的 markdown 语法解析器

    1. 什么是 markdown Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的 ...

  6. java:jsp: 一个简单的自定义标签 tld

    java:jsp: 一个简单的自定义标签 tld 请注意,uri都是:http://www.tag.com/mytag,保持统一,要不然报错,不能访问 tld文件 <?xml version=& ...

  7. js new一个对象的过程,实现一个简单的new方法

    对于大部分前端开发者而言,new一个构造函数或类得到对应实例,是非常普遍的操作了.下面的例子中分别通过构造函数与class类实现了一个简单的创建实例的过程. // ES5构造函数 let Parent ...

  8. 使用JAVA写一个简单的日历

    JAVA写一个简单的日历import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateF ...

  9. Java实现一个简单的网络爬虫

    Java实现一个简单的网络爬虫 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWri ...

随机推荐

  1. 转:void *

    void的含义 void即“无类型”,void *则为“无类型指针”,可以指向任何数据类型. void指针使用规范①void指针可以指向任意类型的数据,亦即可用任意数据类型的指针对void指针赋值.例 ...

  2. DBA_实践指南系列5_Oracle Erp R12日常运维和管理(案例)

    2013-12-05 Created By BaoXinjian

  3. 进程控制块PCB结构 task_struct 描述

    注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...

  4. slub分配器

    Linux的物理内存管理采用了以页为单位的buddy system(伙伴系统),但是很多情况下,内核仅仅需要一个较小的对象空间,而且这些小块的空间对于不同对象又是变化的.不可预测的,所以需要一种类似用 ...

  5. Unix环境高级编程(十四)守护进程实现时间服务器

    守护进程是在后台运行不受终端控制的进程(如输入.输出等),一般的网络服务都是以守护进程的方式运行.守护进程脱离终端的主要原因有两点:(1)用来启动守护进程的终端在启动守护进程之后,需要执行其他任务.( ...

  6. Spring注解运行时抛出null

    关于Spring的注解其实不难,大致需要以下几个流程: 一.配置Spring的注解支持 <?xml version="1.0" encoding="UTF-8&qu ...

  7. 正则表达式写法:Java和Js比较

    1.表示数字 Java:\\d              Js: \d 比如密码写法,Java中:(^[a-zA-Z\\d]{6,20}$),Js中:/^[a-zA-Z\d]{6,20}$/

  8. Nginx访问PHP文件的File not found错误处理,两种情况

    这个错误很常见,原有有下面两种几种 1. php-fpm找不到SCRIPT_FILENAME里执行的php文件 2. php-fpm不能访问所执行的php,也就是权限问题 第一种情况 可以在你的loc ...

  9. How to install Mysql in the CentOS

    This article will walk through you the process of installing and updating latest MySQL 5.7.9 version ...

  10. 鼠标移至div内部其他层时,触发mouseout

    话说有一个DIV元素,其内部有一个IMG元素和SPAN元素,不用理会这两个内部元素怎么布局,这不是我要讨论的重点. 为了实现一些特殊的效果,我需要利用TD的onmouseover和onmouseout ...