读取缓存模拟----FIFO
本例是模拟缓存的存储和读取。
存储:使用一个Map来存放,key是文件名,值为缓存对象
读取:返回相应的key对应的缓存。(如果缓存被修改,就重新加载缓存,再从缓存Map中读取相应缓存)
测试类:每2秒去获取一次缓存日期,如果文件更新了,则会返回新的缓存日期
ReloadHandler :
/**
* 重新加载接口
*
*/
public interface ReloadHandler {
/**
* 分析文件
* @return 要缓存的内容
*/
Object processNewCache() throws Exception;
}
FileCache :
/**
* <pre>
* final 外部对象操作时:
* 通过文件名 -- 在map中找到对应 -- 判断是否修改 --否 -- 返回缓存对象
* |
* 是
* |
* 调用reload,根据传入的handler进行reload,更新缓存对象,更新操作时间
* </pre>
*
*/
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 fileName
* @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() {
} /**
* 缓存元素
*
*/
class CacheElement { public long lastEditTime;
public File file;
public Object cache; public long getLastEditTime() { return lastEditTime;
} public void setLastEditTime(long lastEditTime) { this.lastEditTime = lastEditTime;
} public File getFile() {
return file;
} public void setFile(File file) {
this.file = file;
} public Object getCache() {
return cache;
} public void setCache(Object cache) {
this.cache = cache;
} }
}
测试类:
/**
* 每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("d:/1.txt", new ReloadHandler() {
@Override
public Object processNewCache() {
System.out.print("find change ");
return new Date();
}
});
System.out.println("cacheData:" + date);
}
}
测试方法:
在D盘新建一个1.txt,启动测试类,在程序运行中去更改1.txt中的内容,将得到如下结果:
find change cacheData:Thu Dec 25 15:15:12 CST 2014
cacheData:Thu Dec 25 15:15:12 CST 2014
cacheData:Thu Dec 25 15:15:12 CST 2014
cacheData:Thu Dec 25 15:15:12 CST 2014
find change cacheData:Thu Dec 25 15:15:20 CST 2014
cacheData:Thu Dec 25 15:15:20 CST 2014
cacheData:Thu Dec 25 15:15:20 CST 2014
cacheData:Thu Dec 25 15:15:20 CST 2014
cacheData:Thu Dec 25 15:15:20 CST 2014
cacheData:Thu Dec 25 15:15:20 CST 2014
<转:http://qihigh-hotmail-com.iteye.com/blog/1329702>
读取缓存模拟----FIFO的更多相关文章
- Java实现缓存(LRU,FIFO)
现在软件或者网页的并发量越来越大了,大量请求直接操作数据库会对数据库造成很大的压力,处理大量连接和请求就会需要很长时间,但是实际中百分之80的数据是很少更改的,这样就可以引入缓存来进行读取,减少数据库 ...
- PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [3] 首页 APP 接口开发方案 ② 读取缓存方式
以静态缓存为例. 修改 file.php line:11 去掉 path 参数(方便),加上缓存时间参数: public function cacheData($k,$v = '',$cacheTim ...
- WP_从独立存储区读取缓存的图片
///<summary> /// 独立存储缓存的图片源 /// 用法:item.img = new StorageCachedImage(newUri(http://www.baidu ...
- EF 查询数据不读取缓存的解决办法
EF查询(不使用缓存):Set<T>().AsNoTracking() 今天工作中发现一个很妖的问题,修改产品界面,修改数据后,数据库的值发生变化,感觉掉坑里了. 然后发现读取对象的方法是 ...
- CVE-2017-7529-Nginx越界读取缓存漏洞
漏洞参考 https://blog.csdn.net/qq_29647709/article/details/85076309 漏洞原因 Nginx在反向代理站点的时候,通常会将一些文件进行缓存,特别 ...
- Nginx越界读取缓存漏洞 CVE-2017-7529
1.漏洞描述 Nginx在反向代理站点的时候,通常会将一些文件进行缓存,特别是静态文件.缓存的部分存储在文件中,每个缓存文件包括"文件头"+"HTTP返回包头" ...
- PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [4] 首页 APP 接口开发方案 ③ 定时读取缓存方式
用于 linux 执行 crontab 命令生成缓存的文件 crop.php <?php //让crontab 定时执行的脚本程序 require_once 'db.php'; require_ ...
- 读取AD模拟分量
//EEPROM数据保存---------------------- #include <EEPROM.h> #define EEPROM_write(address, p) {int i ...
- 【操作系统】编程模拟FIFO,LRU,NUR,OPT页面置换算法
#include<stdio.h> #include<stdlib.h> #include<time.h> #define random(x) (rand()%x) ...
随机推荐
- Linux-以指定用户运行redis
redis中无配置启动用户信息,需要添加redis用户,后以其启动 useradd -s /bash/false -M redis >& &
- python数据库连接池
python数据库连接池 import psycopg2 import psycopg2.pool dbpool=psycopg2.pool.PersistentConnectionPool(1,1, ...
- PHP GC垃圾回收机制之引用变量回收周期疑问
普通的引用变量的销毁大家都知道, 当unset的时候如果refcount = 0 则认为无用, 销毁. 但是手册中提到一点会有递归引用的问题,很是奇葩 代码如下 <?php $a = 1; $a ...
- bash内部命令-2
http://www.gnu.org/software/bash/ http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/ [root@250-shiyan ~]# ...
- linux工具之log4j-LogBack-slf4j-commons-logging
log4j http://commons.apache.org/proper/commons-logging/ http://logging.apache.org/log4j/2.x/ The Com ...
- ant脚本编写
使用ant脚本前的准备 1.下载一个ant安装包.如:apache-ant-1.8.4-bin.zip.解压到E盘. 2.配置环境变量.新增ANT_HOME:E:\apache-ant-1.8.4:P ...
- datatables的Bootstrap样式的分页怎么添加首页和尾页(引)
找到dataTables.bootstrap.js(版本3):(此项目中文件名为:dataTableExt.js) $.fn.dataTableExt.oApi.fnPagingInfo = func ...
- log4j的ConversionPattern参数的格式含义-转
转自:http://www.blogjava.net/wilesun/archive/2007/10/30/156999.html Log4j建议只使用四个级别,优先级从高到低分别是ERROR.WAR ...
- ORACLE 常用日期函数
1 . add_months(arg1,num) 返回日期arg1加num个月的新日期. select add_months(date'2011-1-1',1) from dual; result: ...
- spring 中事务的PROPAGATION_REQUIRED,Readonly的解释
一.事务传播行为种类 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为, 它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播 ...