Java 实现本地缓存工具

本次更新:将继承ConcurrentHashMap 改为直接使用ConcurrentHashMap 


基本思路:

1、继承线程安全的ConcurrentHashMap 

1、使用线程安全的ConcurrentHashMap 
2、增加定时器配置信息
3、缓存工具使用单例模式
4、定义put 与 get 方法
5、定义一个 put 方法,增加一个缓存时间参数


经测试:存储100万以内普通数据的频繁读写性能还可以,能满足中小型系统缓存需求,如果要多机器共享缓存,建议单独部署一个缓存服务器


/**   
 * @Title: LocalCache.java 
 * @Package com.yitianyike.utils 
 * @Description: TODO(用一句话描述该文件做什么) 
 * @author Aaron·Li   
 * @date 2016年11月29日 下午6:28:52 
 * @version V1.0   
 */
package com.yitianyike.cache.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;

/**
 * 本地缓存工具(不建议存储量超过50万)
 * 
 * @author Aaron·Li
 * @date 2016年11月29日 下午6:28:52
 */
public class LocalCache implements Serializable {
	private static ConcurrentHashMap
   
   
    
     cache = new ConcurrentHashMap<>();
	private static Logger log = Logger.getLogger(LocalCache.class);
	private static List
    
    
     
      removeList = new ArrayList
     
     
      
      ();
	private static final long serialVersionUID = -3273454956563078833L;
	private static boolean isRun = false;// 用于防止定时任务叠加执行
	private static Timer timer;
	private static LocalCache localCache;
	private static byte[] lock = new byte[0];
	/**
	 * 定时器清理间隔(默认60秒钟执行一次)
	 */
	private static Long DEFAULT_TASK_DELAY = 60000L;

	/**
	 * 存储有效期,默认存储30分钟
	 */
	private static Long DEFAULT_TIMEOUT = 60000 * 30L;

	private LocalCache() {
	}

	public static void setDefaultTimeout(Long timeout) {
		if (timeout > 0) {
			DEFAULT_TIMEOUT = timeout;
		}
	}

	public static void setDefaultClearDelay(Long delay) {
		if (delay >= 500) {
			DEFAULT_TASK_DELAY = delay;
		}
	}

	public static Long getDefaultTimeout() {
		return DEFAULT_TIMEOUT;
	}

	public static Long getDefaultClearDelay() {
		return DEFAULT_TASK_DELAY;
	}

	private static void clearCache() {
		if (!isRun) {
			synchronized (lock) {
				try {
					if (removeList.isEmpty() == false) {
						removeList.clear();
					}
					isRun = true;
					long start = System.currentTimeMillis();
					if (!cache.isEmpty()) {
						Iterator
      
      
       
       
         > i = cache.entrySet().iterator(); while (i.hasNext()) { Entry 
        
          e = i.next(); if (e.getValue() == null) { removeList.add(e.getKey()); } else { if (e.getValue().isTimeout()) { removeList.add(e.getKey()); } } } for (String key : removeList) { cache.remove(key); } } int clearSize = removeList.size(); removeList.clear(); log.debug("本次清理:" + clearSize + ",当前剩余:" + cache.size() + ",清理用时:" + (System.currentTimeMillis() - start) + "毫秒"); } finally { isRun = false; } } } } public static LocalCache createLocalCache() { synchronized (lock) { if (localCache == null) { localCache = new LocalCache(); timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { clearCache(); } }, 0, DEFAULT_TASK_DELAY); } } return localCache; } public boolean containsKey(String key) { return get(key) != null; } public Object get(String key) { if (key != null) { Object obj = null; if (cache.containsKey(key)) { obj = cache.get(key); } if (obj != null) { CacheValue cvalue = (CacheValue) obj; return cvalue.getValue(); } } return null; } /** * 默认缓存 30分钟 */ public Object put(String key, Object value) { return put(key, value, DEFAULT_TIMEOUT); } /** * * @param key * @param value * @param timeout * 单位默认是秒,传入小于0的值则使用默认值(30分钟),传入0 则永久有效(应用重启后失效,目前没有实现存盘) * @return */ public Object put(String key, Object value, Long timeout) { if (key == null) { return null; } CacheValue cvalue = new CacheValue(); cvalue.setKey(key); if (timeout > 0) { cvalue.setTimeout(timeout * 1000L); } else if (timeout < 0) { cvalue.setTimeout(DEFAULT_TIMEOUT); } else { cvalue.setTimeout(0L); } cvalue.setValue(value); return cache.put(key, cvalue); } class CacheValue implements Serializable { private static final long serialVersionUID = 800800964682488492L; private String key; private Long createTime; private Long timeout; private Object value; public CacheValue() { createTime = System.currentTimeMillis() - 100;// 将创建时间提前100毫秒,防止定时回收任务因上一次执行时间过长导致回收滞后 } /** * 判断对象是否已经失效 * * @return 返回 true 失效 false 没有失效 */ public boolean isTimeout() { boolean ret = true; if (value != null) { if (timeout == 0) { return false; } else { ret = System.currentTimeMillis() - createTime >= timeout; if (ret) { value = null; } } } return ret; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public Long getCreateTime() { return createTime; } public Long getTimeout() { return timeout; } public void setTimeout(Long timeout) { this.timeout = timeout; } public Object getValue() { isTimeout(); return value; } public void setValue(Object value) { this.value = value; } } public void remove(String key) { cache.remove(key); } public long size() { return cache.size(); } } 
         
       
      
      
     
     
    
    
   
   
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值