(转载)java本地缓存实现

在java web 项目中对频繁读取且相对稳定的数据一般都是用了缓存,这样可以极大地减少数据库的压力且提高的响应的速度。 一般都是,通过key 从缓存中读取value 如果value 为空则读取DB,将DB读取的数据再放入缓存这样的一个过程。

一个简易的本地缓存实现。

      首先数据一般都是有时效性的,不是放入缓存就一直存在,如果超过一定时间没有被使用则应当被清空,使其系统中不会使用到过期数据。

      下面是对本地缓存的一种简单实现

           首先定义一个缓存实体,包含三个属性 放入缓存的时间戳,值以及过期时间;其次需要个线程去监控缓存实体是否过期。

 

Java代码   收藏代码
  1. /** 
  2. * 
  3. * @author zhangwei_david 
  4. * @version $Id: CacheEntity.java, v 0.1 2014年9月6日 下午2:07:00 Lenovo Exp $ 
  5. */  
  6. /** 
  7. *本地缓存保存的实体 
  8. * 
  9. * @author Lenovo 
  10. * @version $Id: LocalCache.java, v 0.1 2014年9月6日 下午1:13:43 Lenovo Exp $ 
  11. */  
  12. public class CacheEntity implements Serializable {  
  13.   
  14. /** */  
  15. private static final long serialVersionUID = 7172649826282703560L;  
  16.   
  17. /** 
  18. * 值 
  19. */  
  20. private Object value;  
  21.   
  22. /** 
  23. * 保存的时间戳 
  24. */  
  25. private long gmtModify;  
  26.   
  27. /** 
  28. * 过期时间 
  29. */  
  30. private int expire;  
  31.   
  32. public Object getValue() {  
  33. return value;  
  34. }  
  35.   
  36. public void setValue(Object value) {  
  37. this.value = value;  
  38. }  
  39.   
  40. public long getGmtModify() {  
  41. return gmtModify;  
  42. }  
  43.   
  44. public void setGmtModify(long gmtModify) {  
  45. this.gmtModify = gmtModify;  
  46. }  
  47.   
  48. public int getExpire() {  
  49. return expire;  
  50. }  
  51.   
  52. public void setExpire(int expire) {  
  53. this.expire = expire;  
  54. }  
  55.   
  56. public CacheEntity(Object value, long gmtModify, int expire) {  
  57. super();  
  58. this.value = value;  
  59. this.gmtModify = gmtModify;  
  60. this.expire = expire;  
  61. }  
  62.   
  63. }  

 

Java代码   收藏代码
  1. /** 
  2. * 简易本地缓存的实现类 
  3. * @author zhangwei_david 
  4. * @version $Id: LocalCache.java, v 0.1 2014年9月6日 下午1:04:53 zhangwei_david Exp $ 
  5. */  
  6. public class LocalCache {  
  7. //默认的缓存容量  
  8. private static int DEFAULT_CAPACITY = 512;  
  9. //最大容量  
  10. private static int MAX_CAPACITY = 100000;  
  11. //刷新缓存的频率  
  12. private static int MONITOR_DURATION = 2;  
  13. // 启动监控线程  
  14. static {  
  15. new Thread(new TimeoutTimerThread()).start();  
  16. }  
  17. //使用默认容量创建一个Map  
  18. private static ConcurrentHashMap<String, CacheEntity> cache = new ConcurrentHashMap<String, CacheEntity>(  
  19. DEFAULT_CAPACITY);  
  20.   
  21. /** 
  22. * 将key-value 保存到本地缓存并制定该缓存的过期时间 
  23. * 
  24. * @param key 
  25. * @param value 
  26. * @param expireTime 过期时间,如果是-1 则表示永不过期 
  27. * @return 
  28. */  
  29. public boolean putValue(String key, Object value, int expireTime) {  
  30. return putCloneValue(key, value, expireTime);  
  31. }  
  32.   
  33. /** 
  34. * 将值通过序列化clone 处理后保存到缓存中,可以解决值引用的问题 
  35. * 
  36. * @param key 
  37. * @param value 
  38. * @param expireTime 
  39. * @return 
  40. */  
  41. private boolean putCloneValue(String key, Object value, int expireTime) {  
  42. try {  
  43. if (cache.size() >= MAX_CAPACITY) {  
  44. return false;  
  45. }  
  46. // 序列化赋值  
  47. CacheEntity entityClone = clone(new CacheEntity(value, System.nanoTime(), expireTime));  
  48. cache.put(key, entityClone);  
  49. return true;  
  50. catch (Exception e) {  
  51. e.printStackTrace();  
  52. }  
  53. return false;  
  54. }  
  55.   
  56. /** 
  57. * 
  58. * 序列化 克隆处理 
  59. * @param object 
  60. * @return 
  61. */  
  62. private <T extends Serializable> T clone(T object) {  
  63. T cloneObject = null;  
  64. try {  
  65. ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  66. ObjectOutputStream oos = new ObjectOutputStream(baos);  
  67. oos.writeObject(object);  
  68. oos.close();  
  69. ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());  
  70. ObjectInputStream ois = new ObjectInputStream(bais);  
  71. cloneObject = (T) ois.readObject();  
  72. ois.close();  
  73. catch (Exception e) {  
  74. e.printStackTrace();  
  75. }  
  76. return cloneObject;  
  77. }  
  78.   
  79. /** 
  80. *从本地缓存中获取key对应的值,如果该值不存则则返回null 
  81. * 
  82. * @param key 
  83. * @return 
  84. */  
  85. public Object getValue(String key) {  
  86. return cache.get(key).getValue();  
  87.   
  88. }  
  89.   
  90. /** 
  91. * 清空所有 
  92. */  
  93. public void clear() {  
  94. cache.clear();  
  95. }  
  96.   
  97. /** 
  98. * 过期处理线程 
  99. * 
  100. * @author Lenovo 
  101. * @version $Id: LocalCache.java, v 0.1 2014年9月6日 下午1:34:23 Lenovo Exp $ 
  102. */  
  103. static class TimeoutTimerThread implements Runnable {  
  104. public void run() {  
  105. while (true) {  
  106. try {  
  107. System.out.println("Cache monitor");  
  108. TimeUnit.SECONDS.sleep(MONITOR_DURATION);  
  109. checkTime();  
  110. catch (Exception e) {  
  111. e.printStackTrace();  
  112. }  
  113. }  
  114. }  
  115.   
  116. /** 
  117. * 过期缓存的具体处理方法 
  118. * @throws Exception 
  119. */  
  120. private void checkTime() throws Exception {  
  121. //"开始处理过期 ";  
  122.   
  123. for (String key : cache.keySet()) {  
  124. CacheEntity tce = cache.get(key);  
  125. long timoutTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime()  
  126. - tce.getGmtModify());  
  127. //" 过期时间 : "+timoutTime);  
  128. if (tce.getExpire() > timoutTime) {  
  129. continue;  
  130. }  
  131. System.out.println(" 清除过期缓存 : " + key);  
  132. //清除过期缓存和删除对应的缓存队列  
  133. cache.remove(key);  
  134. }  
  135. }  
  136. }  
  137.   
  138. }  

转载地址:http://zhangwei-david.iteye.com/blog/2179087

猜你喜欢

转载自cfyme.iteye.com/blog/2207879