今天就跟大家聊聊有关LocalCache在Java项目中如何实现本地缓存,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
成都创新互联自2013年创立以来,先为依安等服务建站,依安等地企业,进行企业商务咨询服务。为依安企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。
一、本地缓存应用场景
localcache有着极大的性能优势:
1. 单机情况下适当使用localcache会使应用的性能得到很大的提升。
2. 集群环境下对于敏感性要求不高的数据可以使用localcache,只配置简单的失效机制来保证数据的相对一致性。
哪些数据可以存储到本地缓存?
1.访问频繁的数据;
2.静态基础数据(长时间内不变的数据);
3.相对静态数据(短时间内不变的数据)。
二、java本地缓存标准
Java缓存新标准(javax.cache),这个标准由JSR107所提出,已经被包含在Java EE 7中。
特性:
1.原子操作,跟java.util.ConcurrentMap类似
2.从缓存中读取
3.写入缓存
4.缓存事件监听器
5.数据统计
6.包含所有隔离(ioslation)级别的事务
7.缓存注解(annotations)
8.保存定义key和值类型的泛型缓存
9.引用保存(只适用于堆缓存)和值保存定义
但目前应用不是很普遍。
三、java开源缓存框架
比较有名的本地缓存开源框架有:
1.EHCache
EHCache是一个纯java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate2.1充当可插入的缓存,最小的依赖性,全面的文档和测试。
BUG: 过期失效的缓存元素无法被GC掉,时间越长缓存越多,内存占用越大,导致内存泄漏的概率越大。
2.OSCache
OSCache有以下特点:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
3.JCache
Java缓存新标准(javax.cache)
4.cache4j
cache4j是一个有简单API与实现快速的Java对象缓存。它的特性包括:在内存中进行缓存,设计用于多线程环境,两种实现:同步与阻塞,多种缓存清除策略:LFU, LRU, FIFO,可使用强引用。
5.ShiftOne
ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。
6.WhirlyCache
Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。
四、LocalCache实现
1、LocalCache简介
LocalCache是一个精简版本地缓存组件,有以下特点:
1. 有容量上限maxCapacity;
2. 缓存达到容量上限时基于LRU策略来移除缓存元素;
3. 缓存对象的生命周期(缓存失效时间)由调用方决定;
4. 缓存对象失效后,将会有定时清理线程来清理掉,不会导致内存泄漏。
5. 性能比Ehcache稍强。
2、总体设计
LocalCache总体设计:
1. 缓存元素 CacheElement;
2. 缓存容器 LRULinkedHashMap;
3. 缓存接口 Cache;
4. 缓存组件实现 LocalCache。
3、详细设计
1. CacheElement设计
/**
* 缓存元素
*
*/
public class CacheElement {
private Object key;
private Object value;
private long createTime;
private long lifeTime;
private int hitCount;
public CacheElement() {
}
public CacheElement(Object key ,Object value) {
this.key = key;
this.value = value;
this.createTime = System.currentTimeMillis();
}
public Object getKey() {
return key;
}
public void setKey(Object key) {
this.key = key;
}
public Object getValue() {
hitCount++;
return value;
}
public void setValue(Object value) {
this.value = value;
}
public long getCreateTime() {
return createTime;
}
public void setCreateTime(long createTime) {
this.createTime = createTime;
}
public int getHitCount() {
return hitCount;
}
public void setHitCount(int hitCount) {
this.hitCount = hitCount;
}
public long getLifeTime() {
return lifeTime;
}
public void setLifeTime(long lifeTime) {
this.lifeTime = lifeTime;
}
public boolean isExpired() {
boolean isExpired = System.currentTimeMillis() - getCreateTime() > getLifeTime();
return isExpired;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("[ key=").append(key).append(", isExpired=").append(isExpired())
.append(", lifeTime=").append(lifeTime).append(", createTime=").append(createTime)
.append(", hitCount=").append(hitCount)
.append(", value=").append(value).append(" ]");
return sb.toString();
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public final int hashCode(){
if(null == key){
return "".hashCode();
}
return this.key.hashCode();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public final boolean equals(Object object) {
if ((object == null) || (!(object instanceof CacheElement))) {
return false;
}
CacheElement element = (CacheElement) object;
if ((this.key == null) || (element.getKey() == null)) {
return false;
}
return this.key.equals(element.getKey());
}
}
2. LRULinkedHashMap实现
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 实现 LRU策略的 LinkedHashMap
*
* @param
* @param
*/
public class LRULinkedHashMap extends LinkedHashMap
{
protected static final long serialVersionUID = 2828675280716975892L;
protected static final int DEFAULT_MAX_ENTRIES = 100;
protected final int initialCapacity;
protected final int maxCapacity;
protected boolean enableRemoveEldestEntry = true;//是否允许自动移除比较旧的元素(添加元素时)
protected static final float DEFAULT_LOAD_FACTOR = 0.8f;
protected final Lock lock = new ReentrantLock();
public LRULinkedHashMap(int initialCapacity)
{
this(initialCapacity, DEFAULT_MAX_ENTRIES);
}
public LRULinkedHashMap(int initialCapacity ,int maxCapacity)
{
//set accessOrder=true, LRU
super(initialCapacity, DEFAULT_LOAD_FACTOR, true);
this.initialCapacity = initialCapacity;
this.maxCapacity = maxCapacity;
}
/*
* (non-Javadoc)
* @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
*/
protected boolean removeEldestEntry(java.util.Map.Entry eldest)
{
return enableRemoveEldestEntry && ( size() > maxCapacity );
}
/*
* (non-Javadoc)
* @see java.util.LinkedHashMap#get(java.lang.Object)
*/
public V get(Object key)
{
try {
lock.lock();
return super.get(key);
}
finally {
lock.unlock();
}
}
/*
* (non-Javadoc)
* @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
*/
public V put(K key, V value)
{
try {
lock.lock();
return super.put(key, value);
}
finally {
lock.unlock();
}
}
/*
* (non-Javadoc)
* @see java.util.HashMap#remove(java.lang.Object)
*/
public V remove(Object key) {
try {
lock.lock();
return super.remove(key);
}
finally {
lock.unlock();
}
}
/*
* (non-Javadoc)
* @see java.util.LinkedHashMap#clear()
*/
public void clear() {
try {
lock.lock();
super.clear();
}
finally {
lock.unlock();
}
}
/*
* (non-Javadoc)
* @see java.util.HashMap#keySet()
*/
public Set keySet() {
try {
lock.lock();
return super.keySet();
}
finally {
lock.unlock();
}
}
public boolean isEnableRemoveEldestEntry() {
return enableRemoveEldestEntry;
}
public void setEnableRemoveEldestEntry(boolean enableRemoveEldestEntry) {
this.enableRemoveEldestEntry = enableRemoveEldestEntry;
}
public int getInitialCapacity() {
return initialCapacity;
}
public int getMaxCapacity() {
return maxCapacity;
}
}
3. Cache接口设计
/**
* 缓存接口
*
*/
public interface Cache {
/**
* 获取缓存
* @param key
* @return
*/
public T getCache(Object key);
/**
* 缓存对象
* @param key
* @param value
* @param milliSecond 缓存生命周期(毫秒)
*/
public void putCache(Object key, Object value ,Long milliSecond);
/**
* 缓存容器中是否包含 key
* @param key
* @return
*/
public boolean containsKey(Object key);
/**
* 缓存列表大小
* @return
*/
public int getSize();
/**
* 是否启用缓存
*/
public boolean isEnabled();
/**
* 启用 或 停止
* @param enable
*/
public void setEnabled(boolean enabled);
/**
* 移除所有缓存
*/
public void invalidateCaches();
/**
* 移除 指定key缓存
* @param key
*/
public void invalidateCache(Object key);
}
4. LocalCache实现
import java.util.Date;
import java.util.Iterator;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 本地缓存组件
*/
public class LocalCache implements Cache{
private Logger logger = LoggerFactory.getLogger(this.getClass());
private LRULinkedHashMap
看完上述内容,你们对LocalCache在Java项目中如何实现本地缓存有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注创新互联行业资讯频道,感谢大家的支持。
文章标题:LocalCache在Java项目中如何实现本地缓存
浏览地址:
http://ybzwz.com/article/geedep.html