读取缓存模拟----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) ...
随机推荐
- error LNK2026: 模块对于 SAFESEH 映像是不安全的
解决方法: 1.打开该项目的“属性页”对话框. 2.单击“链接器”文件夹. 3.单击“命令行”属性页. 4.将 /SAFESEH:NO 键入“附加选项”框中,然后点击应用.
- #你好Unity3D#Hierarchy视图监听gameObject点击事件
今天无意间又找到了个好方法 1 2 3 4 5 6 7 8 9 10 [InitializeOnLoadMethod] static void Start () { Selection.s ...
- 简单实用的Android ORM框架TigerDB
TigerDB是一个简单的Android ORM框架,它能让你一句话实现数据库的增删改查,同时支持实体对象的持久化和自动映射,同时你也不必关心表结构的变化,因为它会自动检测新增字段来更新你的表结构. ...
- css设置透明度
使用新的CSS3的"RGBA"声明,不仅仅让我们像通常一样设置RGB颜色,而且还可以设置其透明度. RGBA像RGB一样设置颜色,而这个"A"--RGBA中的最 ...
- jQuery根据文本设置select选中失效问题
$("#select_id option[text='jQuery']").attr("selected", true) 失效 text是Jquery关键字,不 ...
- IE7中line-height垂直居中问题
line-height:24px; *+line-height:24px; //针对ie7 height:24px
- maven 常见错误解决
1. maven打包编译时后台一直输出警告信息 [WARNING] File encoding has not been set, using platform encoding GBK, i.e. ...
- HBase(一): c#访问hbase组件开发
HDP2.4安装系列介绍了通过ambari创建hbase集群的过程,但工作中一直采用.net的技术路线,如何去访问基于Java搞的Hbase呢? Hbase提供基于Java的本地API访问,同时扩展了 ...
- 【redis】 linux 下redis 集群环境搭建
Redis集群 (要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点,对应的redis节点的ip和端口对应关系如下) 127.0.0.1:63791 ...
- c# 中的多线程和异步
前言: 1.异步和多线程有区别吗? 答案:多线程可以说是实现异步的一种方法方法,两者的共同目的:使主线程保持对用户操作的实时响应,如点击.拖拽.输入字符等.使主程序看起来实时都保持着等待用户响应的状态 ...