读书人

java资料读取缓存类

发布时间: 2012-09-22 21:54:54 作者: rapoo

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

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

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

接口:

/** * 重新加载接口 * @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 2011Wed Dec 28 15:25:46 CST 2011Wed Dec 28 15:25:46 CST 2011Wed Dec 28 15:25:46 CST 2011find change  Wed Dec 28 15:25:56 CST 2011Wed Dec 28 15:25:56 CST 2011Wed Dec 28 15:25:56 CST 2011Wed Dec 28 15:25:56 CST 2011Wed 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);    }

读书人网 >编程

热点推荐