java文件读取缓存类

[size=medium] 流程图:
<pre>
final 外部对象操作时:
通过文件名 -- 在map中找到对应 -- 判断是否修改 --否 -- 返回缓存对象
|

|
调用reload,根据传入的handler进行reload,更新缓存对象,更新操作时间
</pre>

主要根据的是文件的修改时间,如果本次读取时的修改时间和缓存中的时间相同,则直接返回缓存,否则的话就重新加载文件,更新缓存和时间
重新加载文件的时候需要传入一个 ReloadHandler,以实现更大的灵活性(策略模式),返回一个新的对象并缓存
(待完善:自动清理功能
方案1:FIFO 最简单,但是效率比较低
方案2:访问次数多的留下,少的去掉
方案3:记得大学里编译原理有个更好的方式,忘记了。
)暂时用FIFO
[/size]
接口:
/**
* 重新加载接口
* @author qihuan
*
*/
public interface ReloadHandler {
/**
* 分析文件
* @return 要缓存的内容
*/
Object processNewCache() throws Exception;
}

缓存类:

/**
* <pre>
* final 外部对象操作时:
* 通过文件名 -- 在map中找到对应 -- 判断是否修改 --否 -- 返回缓存对象
* |
* 是
* |
* 调用reload,根据传入的handler进行reload,更新缓存对象,更新操作时间
* </pre>
* @author qihuan
*/
public class FileCache {
/** 缓存map */
private static Map<String, CacheElement> cacheMap = new HashMap<String, CacheElement>();
private static FileCache fileCache;
private static final int MAX_SIZE = 20;
private Queue<String> fileQueue = new LinkedList<String>();

/**
* 单例,多线程一样自信
*
* @return fileCache单例
*/
public static FileCache getInstance(){
if(null == fileCache){
fileCache = new FileCache();
}
return fileCache;
}
/**
* 获取缓存对象
* 获取缓存,如果文件被修改,则重新加载最近配置,内存中超过20个文件缓存,会自动清理
* @param fileName
* @return
* @throws Exception
*/
public Object getCache(String fileName,ReloadHandler handler) throws Exception{
fileName = fileName.trim();
if(isModified(fileName)){
reLoad(fileName,handler);
}
return cacheMap.get(fileName).getCache();
}

/**
* 重新加载
* @param fileName
* @param handler
* @throws Exception
*/
private void reLoad(String fileName, ReloadHandler handler) throws Exception {
CacheElement ele = cacheMap.get(fileName);
if(null == ele){
//文件没有加载过
ele = new CacheElement();
//设置File对象
ele.setFile(new File(fileName));
cacheMap.put(fileName, ele);
//添加新的缓存,记录到队列中
if(!fileQueue.contains(fileName)){
//如果队列中没记录这个,则试图添加并进行清理
cacheClean();
fileQueue.add(fileName);
}
}
//更新缓存
ele.setCache(handler.processNewCache());
//更新修改时间
ele.setLastEditTime(ele.getFile().lastModified());

}
/**
* 判断是否已经修改
*
* @param diXmlName
* @return
*/
private boolean isModified(String fileName) {

CacheElement cacheElement = cacheMap.get(fileName);
if (null == cacheElement) {
//配置文件没有被加载过
return true;
}
if (cacheElement.getFile().lastModified() != cacheElement.getLastEditTime()) {
//被修改
return true;
}
// 没有变化
return false;
}

/**
* FIFO 清理缓存,
*/
private void cacheClean(){
//缓存超过限制之后,进行清理
if(fileQueue.size() >= MAX_SIZE ){
String fileName = fileQueue.poll();
cacheMap.put(fileName, null);
cacheMap.remove(fileName);
}
}

//私有构造
private FileCache(){}
/**
* 缓存元素
*
* @author qihuan
*/
class CacheElement {

public long lastEditTime;
public File file;
public Object cache;

public long getLastEditTime() {

return lastEditTime;
}

public void setLastEditTime(long lastEditTime) {

this.lastEditTime = lastEditTime;
}

//setters and getters...
}
}



缓存一个文件的测试类:

测试类:
/**
* 每2秒去获取一次缓存日期,如果文件更新了,则会返回新的缓存日期
*/
public class CacheTest {

@Test
public void getFileContent() {

int count = 10;
while (count-- > 0) {
try {
getCache();
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}

private void getCache() throws Exception {

Date date = (Date)FileCache.getInstance().getCache("e:/1.txt", new ReloadHandler() {

@Override
public Object processNewCache() {
System.out.print("find change ");
return new Date();
}
});
System.out.println(date);
}
}
output:
find change Wed Dec 28 15:25:46 CST 2011 (初始化)
Wed Dec 28 15:25:46 CST 2011
Wed Dec 28 15:25:46 CST 2011
Wed Dec 28 15:25:46 CST 2011
Wed Dec 28 15:25:46 CST 2011
find change Wed Dec 28 15:25:56 CST 2011
Wed Dec 28 15:25:56 CST 2011
Wed Dec 28 15:25:56 CST 2011
Wed Dec 28 15:25:56 CST 2011
Wed Dec 28 15:25:56 CST 2011



实际应用时代码片段

/**
* 获取配置
*
* @param diXmlName
* 接口配置文件名称
* @param diXmlPath
* 接口配置文件完整路径
* @return
* @throws DataConfigException
*/
public DataInterfaceConfig getConfig(final String diXmlName) throws DataConfigException {
DataInterfaceConfig config = null;
final String diXmlPath = Constant.CONFIG_HOME + File.separator + "diConfig" + File.separator + diXmlName;
try {
config = (DataInterfaceConfig) FileCache.getInstance().getCache(diXmlPath, new ReloadHandler() {

@Override
public Object processNewCache() throws Exception {

//重新加载配置文件
return DataInterfaceConfigParser.parser(diXmlPath);
}
});
} catch (Exception e) {
throw new DataConfigException(e);
}
return config;
}


/**
* 从缓存中 根据code 获取 接口配置
* @param code
* @return
* @throws BizException
*/
public DataInterface getDataInterfaceByCode(String code) throws BizException{
Map<String,DataInterface> dataInterface = null;
//获取缓存
try {
dataInterface = (Map<String,DataInterface>) FileCache.getInstance().getCache(Constant.CONFIG_HOME + File.separator + Constant.DIGROUP_CONFIG_XML, new ReloadHandler() {

@Override
public Object processNewCache() throws Exception {
return getAllConfigInGroup();
}
});
} catch (Exception e) {
throw new BizException(e);
}
return dataInterface.get(code);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值