前言
本次分享探讨java平台的本地缓存,是指占用JVM的heap区域来缓冲存储数据的缓存组件。
一、本地缓存应用场景
localcache有着极大的性能优势:
1.单机情况下适当使用localcache会使应用的性能得到很大的提升。
2.集群环境下对于敏感性要求不高的数据可以使用localcache,只配置简单的失效机制来保证数据的相对一致性。
哪些数据可以存储到本地缓存?
1.访问频繁的数据;
2.静态基础数据(长时间内不变的数据);
3.相对静态数据(短时间内不变的数据)。
二、java本地缓存标准
Java缓存新标准(javax.cache),这个标准由JSR107所提出,已经被包含在JavaEE7中。
特性:
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--OSCacheAPI给你全面的程序来控制所有的OSCache特性。永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
3.JCache
Java缓存新标准(javax.cache)
4.cache4j
cache4j是一个有简单API与实现快速的Java对象缓存。它的特性包括:在内存中进行缓存,设计用于多线程环境,两种实现:同步与阻塞,多种缓存清除策略:LFU,LRU,FIFO,可使用强引用。
5.ShiftOne
ShiftOneJavaObjectCache是一个执行一系列严格的对象缓存策略的Javalib,就像一个轻量级的配置缓存工作状态的框架。
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设计
/**
*缓存元素
*
*/
publicclassCacheElement{
privateObjectkey;
privateObjectvalue;
privatelongcreateTime;
privatelonglifeTime;
privateinthitCount;
publicCacheElement(){
}
publicCacheElement(Objectkey,Objectvalue){
this.key=key;
this.value=value;
this.createTime=System.currentTimeMillis();
}
publicObjectgetKey(){
returnkey;
}
publicvoidsetKey(Objectkey){
this.key=key;
}
publicObjectgetValue(){
hitCount++;
returnvalue;
}
publicvoidsetValue(Objectvalue){
this.value=value;
}
publiclonggetCreateTime(){
returncreateTime;
}
publicvoidsetCreateTime(longcreateTime){
this.createTime=createTime;
}
publicintgetHitCount(){
returnhitCount;
}
publicvoidsetHitCount(inthitCount){
this.hitCount=hitCount;
}
publiclonggetLifeTime(){
returnlifeTime;
}
publicvoidsetLifeTime(longlifeTime){
this.lifeTime=lifeTime;
}
publicbooleanisExpired(){
booleanisExpired=System.currentTimeMillis()-getCreateTime()>getLifeTime();
returnisExpired;
}
/*
*(non-Javadoc)
*@seejava.lang.Object#toString()
*/
publicStringtoString(){
StringBuffersb=newStringBuffer();
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("]");
returnsb.toString();
}
/*
*(non-Javadoc)
*@seejava.lang.Object#hashCode()
*/
publicfinalinthashCode(){
if(null==key){
return"".hashCode();
}
returnthis.key.hashCode();
}
/*
*(non-Javadoc)
*@seejava.lang.Object#equals(java.lang.Object)
*/
publicfinalbooleanequals(Objectobject){
if((object==null)||(!(objectinstanceofCacheElement))){
returnfalse;
}
CacheElementelement=(CacheElement)object;
if((this.key==null)||(element.getKey()==null)){
returnfalse;
}
returnthis.key.equals(element.getKey());
}
}
2. LRULinkedHashMap实现
importjava.util.LinkedHashMap;
importjava.util.Set;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
/**
*实现LRU策略的LinkedHashMap
*
*@param
*@param
*/
publicclassLRULinkedHashMapextendsLinkedHashMap
{
protectedstaticfinallongserialVersionUID=2828675280716975892L;
protectedstaticfinalintDEFAULT_MAX_ENTRIES=100;
protectedfinalintinitialCapacity;
protectedfinalintmaxCapacity;
protectedbooleanenableRemoveEldestEntry=true;//是否允许自动移除比较旧的元素(添加元素时)
protectedstaticfinalfloatDEFAULT_LOAD_FACTOR=0.8f;
protectedfinalLocklock=newReentrantLock();
publicLRULinkedHashMap(intinitialCapacity)
{
this(initialCapacity,DEFAULT_MAX_ENTRIES);
}
publicLRULinkedHashMap(intinitialCapacity,intmaxCapacity)
{
//setaccessOrder=true,LRU
super(initialCapacity,DEFAULT_LOAD_FACTOR,true);
this.initialCapacity=initialCapacity;
this.maxCapacity=maxCapacity;
}
/*
*(non-Javadoc)
*@seejava.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
*/
protectedbooleanremoveEldestEntry(java.util.Map.Entryeldest)
{
returnenableRemoveEldestEntry&&(size()>maxCapacity);
}
/*
*(non-Javadoc)
*@seejava.util.LinkedHashMap#get(java.lang.Object)
*/
publicVget(Objectkey)
{
try{
lock.lock();
returnsuper.get(key);
}
finally{
lock.unlock();
}
}
/*
*(non-Javadoc)
*@seejava.util.HashMap#put(java.lang.Object,java.lang.Object)
*/
publicVput(Kkey,Vvalue)
{
try{
lock.lock();
returnsuper.put(key,value);
}
finally{
lock.unlock();
}
}
/*
*(non-Javadoc)
*@seejava.util.HashMap#remove(java.lang.Object)
*/
publicVremove(Objectkey){
try{
lock.lock();
returnsuper.remove(key);
}
finally{
lock.unlock();
}
}
/*
*(non-Javadoc)
*@seejava.util.LinkedHashMap#clear()
*/
publicvoidclear(){
try{
lock.lock();
super.clear();
}
finally{
lock.unlock();
}
}
/*
*(non-Javadoc)
*@seejava.util.HashMap#keySet()
*/
publicSetkeySet(){
try{
lock.lock();
returnsuper.keySet();
}
finally{
lock.unlock();
}
}
publicbooleanisEnableRemoveEldestEntry(){
returnenableRemoveEldestEntry;
}
publicvoidsetEnableRemoveEldestEntry(booleanenableRemoveEldestEntry){
this.enableRemoveEldestEntry=enableRemoveEldestEntry;
}
publicintgetInitialCapacity(){
returninitialCapacity;
}
publicintgetMaxCapacity(){
returnmaxCapacity;
}
}
3. Cache接口设计
/**
*缓存接口
*
*/
publicinterfaceCache{
/**
*获取缓存
*@paramkey
*@return
*/
publicTgetCache(Objectkey);
/**
*缓存对象
*@paramkey
*@paramvalue
*@parammilliSecond缓存生命周期(毫秒)
*/
publicvoidputCache(Objectkey,Objectvalue,LongmilliSecond);
/**
*缓存容器中是否包含key
*@paramkey
*@return
*/
publicbooleancontainsKey(Objectkey);
/**
*缓存列表大小
*@return
*/
publicintgetSize();
/**
*是否启用缓存
*/
publicbooleanisEnabled();
/**
*启用或停止
*@paramenable
*/
publicvoidsetEnabled(booleanenabled);
/**
*移除所有缓存
*/
publicvoidinvalidateCaches();
/**
*移除指定key缓存
*@paramkey
*/
publicvoidinvalidateCache(Objectkey);
}
4. LocalCache实现
importjava.util.Date;
importjava.util.Iterator;
importjava.util.Random;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
/**
*本地缓存组件
*/
publicclassLocalCacheimplementsCache{
privateLoggerlogger=LoggerFactory.getLogger(this.getClass());
privateLRULinkedHashMap
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。