在实际项目中,我们经常会需要使用到缓存。一般来说,缓存介质是内存;而常见的DB将数据存储在硬盘中的;缓存读取是电脉冲,而硬盘读取是机械地读取转动的硬盘,速度差异是上百倍的。所以往往可以通过缓存,对经常用到的数据进行访问,以提高速度。

创建缓存实际上就是针对两个对象,1. Cache对象,即一个缓存对象;2. CacheManager对象,即一个管理不同缓存的对象,其核心实际上就是一个Map,用来保存与获取不同缓存。

最简单的缓存 实现如下:

/*** 项目名称:

* 文件说明:创建一个缓存管理器 刘晨曦

* 主要特点:

* 版本号:1.0

* 创建时间:2013-12-3

**/

packageNBOffer;importjava.util.HashMap;public classCacheManager {static HashMap cacheMap=new HashMap();public staticCache getCache(String id)

{returncacheMap.get(id);

}public static voidputCache(Cache cache)

{

cacheMap.put(cache.id, cache);

}public static voidmain(String[] args) {

Cache cache1=new Cache("1","A1");

Cache cache2=new Cache("2","A2");

CacheManager.putCache(cache1);

CacheManager.putCache(cache2);

CacheManager.getCache("1").showInfo();

}

}classCache

{

String id;//相当于主键

Object val;publicCache(String id)

{new Cache(id,null);

}publicCache(String id,Object val)

{this.id=id;this.val=val;

}public voidsetValue(Object val)

{this.val=val;

}public voidshowInfo()

{

System.out.println("Cache的ID是: "+id+" Cache的值是: "+val);

}

}

问题1: 哪一步能够体现出缓存相对于直接读取库的优点?

实际上是getCache()方法,是从HashMap中读取,也就是从JVM中读取,处于内存中。

问题2: 缓存若未能命中,岂不是返回空的Cache了?

是的,所以我们需要对getCache进行改进,未能命中说明缓存里面没有,需要从数据库里面取数。

/*** 项目名称:

* 文件说明:创建一个缓存管理器 刘晨曦

* 主要特点:

* 版本号:1.0

* 创建时间:2013-12-3

**/

packageNBOffer;importjava.util.HashMap;public classCacheManager {static HashMap cacheMap=new HashMap();public staticCache getCache(String id)

{if(cacheMap.get(id)==null)

{

Object val=getFromDB(id);

cacheMap.put(id,newCache(id,val));

}returncacheMap.get(id);

}public static voidputCache(Cache cache)

{

cacheMap.put(cache.id, cache);

}public staticObject getFromDB(String id)

{

System.out.println("缓慢地从内存中读取id="+id+"对应的数据。。。");return new String("value"+id);

}public static voidmain(String[] args) {

Cache cache1=new Cache("1","value1");

Cache cache2=new Cache("2","value2");

CacheManager.putCache(cache1);

CacheManager.putCache(cache2);

CacheManager.getCache("3").showInfo();

}

}classCache

{

String id;//相当于主键

Object val;publicCache(String id)

{new Cache(id,null);

}publicCache(String id,Object val)

{this.id=id;this.val=val;

}public voidsetValue(Object val)

{this.val=val;

}public voidshowInfo()

{

System.out.println("Cache的ID是: "+id+" Cache的值是: "+val);

}

}

问题3:如果我想定时一段时间刷新缓存,比如,每隔15min刷新一次所有缓存,那我应该怎么办?

为了方便观察,我们设置为每间隔1s刷新一次。

/*** 项目名称:

* 文件说明:创建一个缓存管理器 刘晨曦

* 主要特点:

* 版本号:1.0

* 创建时间:2013-12-3

**/

packageNBOffer;importjava.util.HashMap;importjava.util.Iterator;importjava.util.Set;public classCacheManager {static HashMap cacheMap=new HashMap();public staticCache getCache(String id)

{if(cacheMap.get(id)==null)

{

Object val=getFromDB(id);

cacheMap.put(id,newCache(id,val));

}returncacheMap.get(id);

}public static voidputCache(Cache cache)

{

cacheMap.put(cache.id, cache);

}public staticObject getFromDB(String id)

{

System.out.println("缓慢地从内存中读取id="+id+"对应的数据。。。");return new String("value"+id);

}public static voidrefreshCaches()

{

System.out.println("刷新缓存。。。");

Set keySet=cacheMap.keySet();

Iterator it=keySet.iterator();while(it.hasNext())

{

String id=(String) it.next();

Object val=getFromDB(id);

cacheMap.put(id,newCache(id,val));

}

}public static voidmain(String[] args) {

Cache cache1=new Cache("1","value1");

Cache cache2=new Cache("2","value2");

CacheManager.putCache(cache1);

CacheManager.putCache(cache2);

CacheManager.getCache("3").showInfo();

Thread refreshTD=newThread()

{public voidrun()

{while(true)

{

refreshCaches();try{

Thread.sleep(1000);//每一秒刷新一次

} catch(InterruptedException e) {

e.printStackTrace();

}

}

}

};

refreshTD.start();

}

}classCache

{

String id;//相当于主键

Object val;publicCache(String id)

{new Cache(id,null);

}publicCache(String id,Object val)

{this.id=id;this.val=val;

}public voidsetValue(Object val)

{this.val=val;

}public voidshowInfo()

{

System.out.println("Cache的ID是: "+id+" Cache的值是: "+val);

}

}

问题4:上面你说的缓存是存在问题的,因为每次你都是统一刷新,有的数据刚刚在14min59s的时候上传的,你就得让它在1s后刷新吗?另外,有的数据变化的很快,不能15min刷新的,而是需要没1min刷新一次,你这样做真的好吗?还有,有的数据在这15min中之内都不会用到,还有必要刷新吗?

上述三个问题的确需要改进,那么我可以针对不同的缓存,并且在自由需要(发送请求+缓存不存在/失效)的时候才进行刷新,再进行优化。代码如下:

/*** 项目名称:

* 文件说明:创建一个缓存管理器 lcx

* 主要特点:

* 版本号:1.0

* 创建时间:2013-12-3

**/

packageNBOffer;importjava.util.Date;importjava.util.HashMap;public classCacheManager {static HashMap cacheMap=new HashMap();public staticCache getCache(String id)

{//对于不存在或者失效的缓存统一处理

if(cacheMap.get(id)==null||!cacheMap.get(id).isValid())

{

Object val=getFromDB(id);

Cache cache=newCache(id,val);

cache.latest=newDate();

cacheMap.put(id, cache);

}returncacheMap.get(id);

}public static voidputCache(Cache cache)

{

cache.latest=newDate();

cacheMap.put(cache.id, cache);

}public staticObject getFromDB(String id)

{

System.out.println("缓慢地从内存中读取id="+id+"对应的数据。。。");return new String("value"+id);

}public static voidmain(String[] args) {

Cache cache1=new Cache("1","value1");

Cache cache2=new Cache("2","value2");

cache2.invalidTime=5000;//设置失效视角是5s

CacheManager.putCache(cache1);

CacheManager.putCache(cache2);try{

Thread.sleep(6000);

}catch(InterruptedException e) {

e.printStackTrace();

}

CacheManager.getCache("1");

CacheManager.getCache("2");

}

}classCache

{

String id;//相当于主键

Object val;

Date latest;//最近刷新时间

long invalidTime=10000;//默认失效时间10s

publicCache(String id)

{new Cache(id,null);

}publicCache(String id,Object val)

{this.id=id;this.val=val;

}public voidsetValue(Object val)

{this.val=val;

}/*** 判断现在缓存是否有效

*@return

*/

public booleanisValid()

{return (new Date()).getTime()-latest.getTime()

}public voidshowInfo()

{

System.out.println("Cache的ID是: "+id+" Cache的值是: "+val);

}

}

问题5:既然都做到这个份上了,那么关于缓存的几个名词都得说说了。

缓存命中率:缓存命中率=从缓存中读数/(缓存读数+磁盘读数)。

缓存失效:缓存超过了失效时间。过期了(也可能有其他原因)。

缓存穿透:对于并不存在的数据,每次都会想DB发送请求,对DB的危害非常大。

缓存雪崩:对于某个失效的缓存在短时间内大量访问,可能造成DB宕机。

缓存算法:LRU、LFU、LIFO

java 建立缓存_java动态缓存——创建一个简单的缓存相关推荐

  1. JAVA程序设计(自主模式)-创建一个简单的表示矩形的Rectangle类

    创建一个简单的表示矩形的Rectangle类,满足以下条件: 1.定义两个成员变量height和width,表示矩形的长和宽,类型为整型 2.定义一个getArea方法,返回矩形的面积 3.定义一个g ...

  2. java 建立索引_java中怎么创建索引

    java中创建索引的方法:首先把对象转换为JSON字符串:然后把json文档写入索引:最后使用Java代码新建一个Java项目,在其中写好创建索引代码调用就可以了. 索引是与表或视图关联的磁盘上结构, ...

  3. java 缓存方法_Java实现一个简单的缓存方法

    Java实现一个简单的缓存方法 发布时间:2020-09-07 21:39:55 来源:脚本之家 阅读:99 作者:BrightLoong 缓存是在web开发中经常用到的,将程序经常使用到或调用到的对 ...

  4. java qq ui界面_java swing 创建一个简单的QQ界面教程

    记录自己用java swing做的第一个简易界面. LoginAction.java package com.QQUI0819; import javax.swing.*; import java.a ...

  5. idea建立一个java工程_IntelliJ IDEA(三、各种工程的创建 -- 之一 -- 创建一个简单的Java工程)...

    一.创建一个简单的Java工程:HelloWorld 1. Eclipse的第一步是选择工作空间,然后创建项目: IDEA不同(没有工作空间的概念),第一步就直接创建具体的项目,项目创建过程中会选择在 ...

  6. 创建一个简单的后台教务管理系统,包含动态增删改查学生,年级和课程信息及查看登录日志等功能,包含表单验证.

    创建一个简单的后台教务管理系统,包含动态增删改查学生,年级和课程信息及查看登录日志等功能,包含表单验证. 一.显示页面 新建一个登录页面,即login.jsp <%--Created by In ...

  7. Spring MVC:使用基于Java的配置创建一个简单的Controller

    这是我博客上与Spring MVC相关的第一篇文章. 开端总是令人兴奋的,因此我将尽量简洁明了. Spring MVC允许以最方便,直接和快速的方式创建Web应用程序. 开始使用这项技术意味着需要Sp ...

  8. Java——创建一个简单的窗口

    今天刚刚上完Java饶有兴趣的我 做了这么一个简单的窗口.挺有成就感的. package RTFIL; import javax.swing.*; import java.awt.*; import ...

  9. 使用java创建一个简单的回合制的双人pk

    创建一个简单的双人pk package com.hp.Demo1;import java.util.Random;/*** 玩家类* 属性:名字.类型.生命值.防御力.攻击类* 方法:自我介绍.Pk* ...

  10. java多线程创建一个简单的案例

    1.创建一个简单的线程,不需要去创建个Runnable Thread thread = new Thread(new Runnable() {@Overridepublic void run() {/ ...

最新文章

  1. 谷歌自曝医疗AI临床结果不佳:实验室丰满,临床骨感
  2. 联想ThinkPad笔记本广告向苹果MacBook Air开战
  3. [2021-09-04 AtCoder Beginner Contest 217] 题解
  4. 你好a+b(非入门)
  5. 使用图形芯片加速电子自动化设计应用程序
  6. 如何计算一只鸡的表面积?
  7. 【数据结构与算法】二项队列与二叉堆的比较
  8. php上传图片显示在当前页,PHP上传图片到数据库并显示
  9. ARM11---中断---向量中断控制器(VIC)---结合s3c6410
  10. 错误:Failed to start component [StandardEngine[Catalina].StandardHost[local
  11. 自己整理实现的python小工具
  12. Go 编码建议——风格篇
  13. 用python制作贺卡_Python:通过邮箱发送贺卡或明信片
  14. Linux下netstat命令详解
  15. 信号与信息处理专业属于计算机类吗,信号与信息处理
  16. 程序员必备的八大排序算法
  17. VS运行程序时遇到0xc0150002的问题
  18. 阿里云国际版服务器电子商务直播解决方案
  19. Linux基础操作命令
  20. python 批量ping_python实现本地批量ping多个IP

热门文章

  1. MATLAB文件操作及读txt文件(fopen,fseek,fread,fclose)
  2. Word(六)-强大的“邮件合并”(2)
  3. 思科3524交换机配置vlan
  4. TCP实现原理(报文段结构+可靠数据传输+流量控制)
  5. 【OpenCV】立体匹配算法SSD、NCC、ASW的基础实现
  6. elementui select 默认值
  7. Keil MDK浮点数支持不正常的解决方案
  8. IIS配置aspnet常见为题
  9. syn flag flooding防御
  10. Map对象,Set对象使用(1)