Cache的作用:
在并发环境中减少重复性的对后台的调用,从而提高运行效率。
Cache必须要做到的:
1.保证Cache中的数据与后台系统数据的一致性。
2.Cache必须要减少访问后台的操作以提高效率。
如果不能同时做到以上两点,则Cache失去了意义。
Cache的基本操作:
Read(Get):按键值从Cache中取得想要的数据;
Write(Put):将键值对放到Cache中;
Reset(RemoveAll):清除Cache中的原有数据;
IsExist(has):判断某键在Cache中是否存在。
Cache中对数据的保护:
因为Cache多用于多线程环境中,需要对数据进行保护;
同步方法,同步块能起到保护的作用,但是效率不高;
读写锁也能起到保护的左右,而且效率较高。
Cache数据的时效性:
使用过期数据是危险的,我们必须确保取出的数据的时效性;
当放入数据时我们可以记录放入的时间,这样取出时就能得到它,然后与当前时间进行比较,如果小于一定间隔则可以认为数据没有时效。间隔一般可以设置为后台数据被更新间隔的平均时间的一半。
Cache的设计:
1.Data类,用以存储数据和放入时间:
import java.io.Serializable;
import java.util.Date;
public class Data implements Serializable{
private static final long serialVersionUID = 8596587790584575734L;
private byte[] value;
private Date date;
public Data(byte[] value,Date date){
this.value=value;
this.date=date;
}
public byte[] getValue() {
return value;
}
public void setValue(byte[] value) {
this.value = value;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
2.ReadWriteLock,用以在并发环境中保护数据:
/**
* Read-write Lock Class
*
* @author heyang
* @time Sep 23, 2011,3:55:55 PM
*/
public class ReadWriteLock {
private boolean isRead;
private boolean isWrite;
/**
* Add Read Lock
*/
public synchronized void readLock(){
while(isWrite){
try{
wait();
}
catch(InterruptedException ex){
ex.printStackTrace();
}
}
isRead=true;
}
/**
* Unlock the read-lock
*/
public synchronized void readUnlock(){
isRead=false;
notifyAll();
}
/**
* Add write lock
*/
public synchronized void writeLock(){
while(isRead){
try{
wait();
}
catch(InterruptedException ex){
ex.printStackTrace();
}
}
while(isWrite){
try{
wait();
}
catch(InterruptedException ex){
ex.printStackTrace();
}
}
isWrite=true;
}
/**
* Unlock the write-lock
*/
public synchronized void writeUnlock(){
isWrite=false;
notifyAll();
}
}
3.AbstractCacheMap,用以提供Cache的接口和操作:
import java.util.Date;
/**
* Parent class of InnerCacheMap & OutterCacheMap
*
* @author heyang
* @time Sep 23, 2011,4:00:45 PM
*/
public abstract class AbstractCacheMap {
private static final int Time_Limit_300 = 300;
// Read-Write lock,for protecting the cacheMap in the Multi-thread environment
private ReadWriteLock lock;
/**
* Contructor
*/
public AbstractCacheMap() {
lock = new ReadWriteLock();
}
/**
* Put key-value pair into cacheMap
* It can be called by any class
* @param key
* @param value
* @throws Exception
*/
public void writeData(String key,byte[] value) throws Exception{
try {
lock.writeLock();
set(key,new Data(value,new Date()));
} finally {
lock.writeUnlock();
}
}
/**
* Put key-value pair into cacheMap,force child-class to implement.
* It only can be called by child-class
* @param key
* @param value
*/
protected abstract void set(String key,Data data) throws Exception;
/**
* Get value by it's key
* It can be called by any class
*
* @param key
* @return
* @throws Exception
*/
public byte[] readData(String key) throws Exception{
try {
lock.readLock();
Data data=get(key);
return data.getValue();
} finally {
lock.readUnlock();
}
}
/**
* Get value by it's key,force child-class to implement.
* It only can be called by child-class
*
* @param key
* @return
* @throws Exception
*/
protected abstract Data get(String key) throws Exception;
/**
* Judge the existence of a key
* It can be called by any class
*
* @param key
* @return
* @throws Exception
*/
public boolean containsKey(String key) throws Exception{
try {
lock.readLock();
if(contains(key)){
Data data=get(key);
return isexceedTimeLimit(data.getDate());
}
return false;
} finally {
lock.readUnlock();
}
}
/**
* Judge the existence of a key,force child-class to implement.
* It only can be called by child-class
*
* @param key
* @return
* @throws Exception
*/
protected abstract boolean contains(String key) throws Exception;
/**
* Remove a key-value pair from cacheMap by it's key
* It can be called by any class
*
* @param key
* @throws Exception
*/
public void removeData(String key) throws Exception{
try {
lock.writeLock();
remove(key);
} finally {
lock.writeUnlock();
}
}
/**
* Remove a key-value pair from cacheMap by it's key
* It only can be called by child-class
*
* @param key
* @return
* @throws Exception
*/
protected abstract void remove(String key) throws Exception;
/**
* Remove all data in the cacheMap
* It can be called by any class
*
* @throws Exception
*/
public void removeAllData() throws Exception{
try {
lock.writeLock();
removeAll();
} finally {
lock.writeUnlock();
}
}
/**
* Remove all data in the cacheMap
* It only can be called by child-class
*
* @param key
* @return
* @throws Exception
*/
protected abstract void removeAll() throws Exception;
/**
* Judge the date whether exceed the time limit
*
* @param date
* @return
*/
private static boolean isexceedTimeLimit(Date date){
long diff = (new Date()).getTime() - date.getTime();
return diff<Time_Limit_300;
}
}
4.InnerCacheMap,用HashMap作为实际内存空间的Cache实现类:
import java.util.HashMap;
import java.util.Map;
import cachemap.base.AbstractCacheMap;
import cachemap.base.Data;
/**
* CacheMap used local HashMap
*
* @author heyang
* @time Sep 23, 2011,3:48:17 PM
*/
public class InnerCacheMap extends AbstractCacheMap{
// essential storage
private Map<String,Data> map;
/**
* Contructor
*/
public InnerCacheMap(){
super();
map=new HashMap<String,Data>();
}
@Override
protected Data get(String key) throws Exception {
return map.get(key);
}
@Override
protected void set(String key, Data value) throws Exception {
map.put(key, value);
}
@Override
protected boolean contains(String key) throws Exception {
return map.containsKey(key);
}
@Override
protected void remove(String key) throws Exception {
map.remove(key);
}
@Override
protected void removeAll() throws Exception {
map.clear();
}
}
5.CacheMapSetter类,用于向Cache中异步写入数据:
import cachemap.base.AbstractCacheMap;
/**
* CacheMapSetter
* It's use is to set a key-value pair into cacheMap
*
* @author heyang
* @time Sep 26, 2011,10:11:36 AM
*/
public final class CacheMapSetter implements Runnable{
// The reference to the cacheMap
private AbstractCacheMap cacheMap;
private String key;
private byte[] value;
/**
* Constuctor
* @param cacheMap
* @param key
* @param value
*/
public CacheMapSetter(AbstractCacheMap cacheMap,String key,byte[] value){
this.cacheMap=cacheMap;
this.key=key;
this.value=value;
new Thread(this).start();
}
@Override
public void run(){
try{
cacheMap.writeData(key, value);
}
catch(Exception ex){
ex.printStackTrace();
}
}
}
6.使用示例:
// Get key
String key=getKey(inputEnv);
// Get operation
String operation=getOperation(inputEnv);
if("READ".equalsIgnoreCase(operation)){
if(cacheMap.containsKey(key)){
byte[] value=cacheMap.readData(key);
// TODO:
.....
}else{
// TODO:
...
}
}else if("WRITE".equalsIgnoreCase(operation)){
if(cacheMap.containsKey(key)){
cacheMap.removeData(key);
}
byte[] value=getValue(outputEnv);
new CacheMapSetter(cacheMap,key, value);
// TODO:
....
}else if("REMOVEALL".equalsIgnoreCase(operation)){
cacheMap.removeAllData();
// TODO:
....
}else{
throw new Exception("Unknown Operation:"+operation);
}
以上类的代码下载: