如何使用Java实现简单的本地缓存?

来源:互联网 发布:网络推广的案例 编辑:程序博客网 时间:2024/05/22 13:15

我们知道,频繁的IO操作(包括网络请求、数据库请求等)是非常耗费时间资源的,同时也会极大的加重数据库等的压力,降低响应速度。因此对经常访问的数据做适当的缓存机制是非常有必要的。一般我们是通过key从缓存中读取value,如果读取不到则读取数据库,将数据库读取到的数据再放入缓存中。

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

下面是对本地缓存的一个简单实现,首先定义一个缓存试题,包含3个属性,放入缓存的时间戳,值和过期时间; 其次需要个线程去监控缓存实体是否过期。

代码如下:

  1. public class CacheEntity implements Serializable {  
  2.   
  3. /** */  
  4. private static final long serialVersionUID = 7172649826282703560L;  
  5.   
  6. /** 
  7. * 值 
  8. */  
  9. private Object value;  
  10.   
  11. /** 
  12. * 保存的时间戳 
  13. */  
  14. private long gmtModify;  
  15.   
  16. /** 
  17. * 过期时间 
  18. */  
  19. private int expire;  
  20.   
  21. public Object getValue() {  
  22. return value;  
  23. }  
  24.   
  25. public void setValue(Object value) {  
  26. this.value = value;  
  27. }  
  28.   
  29. public long getGmtModify() {  
  30. return gmtModify;  
  31. }  
  32.   
  33. public void setGmtModify(long gmtModify) {  
  34. this.gmtModify = gmtModify;  
  35. }  
  36.   
  37. public int getExpire() {  
  38. return expire;  
  39. }  
  40.   
  41. public void setExpire(int expire) {  
  42. this.expire = expire;  
  43. }  
  44.   
  45. public CacheEntity(Object value, long gmtModify, int expire) {  
  46. super();  
  47. this.value = value;  
  48. this.gmtModify = gmtModify;  
  49. this.expire = expire;  
  50. }  
  51. }  

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

原创粉丝点击