WMB入门之十三:使用在Subflow中比较简陋的Cache设计 增加时效处理
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类,用以存储数据和放入时间:
2.ReadWriteLock,用以在并发环境中保护数据:
3.AbstractCacheMap,用以提供Cache的接口和操作:
4.InnerCacheMap,用HashMap作为实际内存空间的Cache实现类:
5.CacheMapSetter类,用于向Cache中异步写入数据:
6.使用示例:
以上类的代码下载:
在并发环境中减少重复性的对后台的调用,从而提高运行效率。
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;
}
}
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();
}
}
* 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;
}
}
/**
* 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();
}
}
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();
}
}
}
/**
* 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);
}
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);
}
以上类的代码下载:
http://www.blogjava.net/Files/heyang/FiveCacheClasses.rar