以下仅是对map对方式讨论。没有对点阵图阵讨论。
作缓存要做以下2点: 

1:清理及更新缓存时机的处理:
. 虚拟机内存不足,清理缓存
.. 缓存时间超时,或访问次数超出, 启动线程更新
2:类和方法的反射 (线程嵌套调用)
reflect.invoke的使用。

JAVA缓存有两种: 
一、文件缓存,是指把数据存储在磁盘上,可以XML格式,也可以序列化文件DAT格式还是其它文件格式。 
二、内存缓存,也就是实现一个类中静态Map,对这个Map进行常规的增删查。

代码如下:内存中的缓存

package atest.hiyaCache;

/**
*
* @author hiyachen
* @version $Revision$
*/
public class AddrDetail { public String latelyKeyword(String province, String city, String county){
System.out.println("AddrDetail.latelyKeyword=" + province + city + county);
return province + city + county;
} public String buildCache(String latelyKeyword){
System.out.println("AddrDetail.buildCache=" + latelyKeyword);
return latelyKeyword;
}
}
package atest.hiyaCache;

public class CacheData {
private Object data;
private long time;
private int count; public CacheData() { } public CacheData(Object data, long time, int count) {
this.data = data;
this.time = time;
this.count = count;
} public CacheData(Object data) {
this.data = data;
this.time = System.currentTimeMillis();
this.count = 1;
} public void addCount() {
count++;
} public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
}
package atest.hiyaCache;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable; import org.apache.commons.logging.Log; //commons-loggings-1.1.1.jar
import org.apache.commons.logging.LogFactory; public class CacheOperation {
private static final Log log = LogFactory.getLog(CacheOperation.class);
private static CacheOperation singleton = null; private Hashtable cacheMap;//存放缓存数据 private ArrayList threadKeys;//处于线程更新中的key值列表 public static CacheOperation getInstance() {
if (singleton == null) {
singleton = new CacheOperation();
}
return singleton;
} private CacheOperation() {
cacheMap = new Hashtable();
threadKeys = new ArrayList();
} /**
* 添加数据缓存
* 与方法getCacheData(String key, long intervalTime, int maxVisitCount)配合使用
* @param key
* @param data
*/
public void addCacheData(String key, Object data) {
addCacheData(key, data, true);
} private void addCacheData(String key, Object data, boolean check) {
if (Runtime.getRuntime().freeMemory() < 5L*1024L*1024L) {//虚拟机内存小于10兆,则清除缓存
log.warn("WEB缓存:内存不足,开始清空缓存!");
removeAllCacheData();
return;
} else if(check && cacheMap.containsKey(key)) {
log.warn("WEB缓存:key值= " + key + " 在缓存中重复, 本次不缓存!");
return;
}
cacheMap.put(key, new CacheData(data));
} /**
* 取得缓存中的数据
* 与方法addCacheData(String key, Object data)配合使用
* @param key
* @param intervalTime 缓存的时间周期,小于等于0时不限制
* @param maxVisitCount 访问累积次数,小于等于0时不限制
* @return
*/
public Object getCacheData(String key, long intervalTime, int maxVisitCount) {
CacheData cacheData = (CacheData)cacheMap.get(key);
if (cacheData == null) {
return null;
}
if (intervalTime > 0 && (System.currentTimeMillis() - cacheData.getTime()) > intervalTime) {
removeCacheData(key);
return null;
}
if (maxVisitCount > 0 && (maxVisitCount - cacheData.getCount()) <= 0) {
removeCacheData(key);
return null;
} else {
cacheData.addCount();
}
return cacheData.getData();
} /**
* 当缓存中数据失效时,用不给定的方法线程更新数据
* @param o 取得数据的对像(该方法是静态方法是不用实例,则传Class实列)
* @param methodName 该对像中的方法
* @param parameters 该方法的参数列表(参数列表中对像都要实现toString方法,若列表中某一参数为空则传它所属类的Class)
* @param intervalTime 缓存的时间周期,小于等于0时不限制
* @param maxVisitCount 访问累积次数,小于等于0时不限制
* @return
*/
public Object getCacheData(Object o, String methodName,Object[] parameters,
long intervalTime, int maxVisitCount) {
Class oc = o instanceof Class ? (Class)o : o.getClass();
StringBuffer key = new StringBuffer(oc.getName());//生成缓存key值
key.append("-").append(methodName);
if (parameters != null) {
for (int i = 0; i < parameters.length; i++) {
if (parameters[i] instanceof Object[]) {
key.append("-").append(Arrays.toString((Object[])parameters[i]));
} else {
key.append("-").append(parameters[i]);
}
}
} CacheData cacheData = (CacheData)cacheMap.get(key.toString());
if (cacheData == null) {//等待加载并返回
Object returnValue = invoke(o, methodName, parameters, key.toString());
return returnValue instanceof Class ? null : returnValue;
}
if (intervalTime > 0 && (System.currentTimeMillis() - cacheData.getTime()) > intervalTime) {
daemonInvoke(o, methodName, parameters, key.toString());//缓存时间超时,启动线程更新数据
} else if (maxVisitCount > 0 && (maxVisitCount - cacheData.getCount()) <= 0) {//访问次数超出,启动线程更新数据
daemonInvoke(o, methodName, parameters, key.toString());
} else {
cacheData.addCount();
}
return cacheData.getData();
} /**
* 递归调用给定方法更新缓存中数据据
* @param o
* @param methodName
* @param parameters
* @param key
* @return 若反射调用方法返回值为空则返回该值的类型
*/
private Object invoke(Object o, String methodName,Object[] parameters, String key) {
Object returnValue = null;
try {
Class[] pcs = null;
if (parameters != null) {
pcs = new Class[parameters.length];
for (int i = 0; i < parameters.length; i++) {
if (parameters[i] instanceof MethodInfo) {
//参数类型是MethodInfo则调用该方法的返回值做这参数
MethodInfo pmi = (MethodInfo)parameters[i];
Object pre = invoke(pmi.getO(), pmi.getMethodName(), pmi.getParameters(), null);
parameters[i] = pre;
}
if (parameters[i] instanceof Class) {
pcs[i] = (Class)parameters[i];
parameters[i] = null;
} else {
pcs[i] = parameters[i].getClass();
}
}
}
Class oc = o instanceof Class ? (Class)o : o.getClass();
//Method m = oc.getDeclaredMethod(methodName, pcs);
Method m = matchMethod(oc, methodName, pcs);
Object o1 = oc.newInstance(); // add by chf
returnValue = m.invoke(o1, parameters);
if (key != null && returnValue != null) {
addCacheData(key, returnValue, false);
}
if (returnValue == null) {
returnValue = m.getReturnType();
}
} catch(Exception e) {
log.error("调用方法失败,methodName=" + methodName);
if (key != null) {
removeCacheData(key);
log.error("更新缓存失败,缓存key=" + key);
}
e.printStackTrace();
}
return returnValue;
} /**
* 找不到完全匹配的方法时,对参数进行向父类匹配
* 因为方法aa(java.util.List) 与 aa(java.util.ArrayList)不能自动匹配到
*
* @param oc
* @param methodName
* @param pcs
* @return
* @throws NoSuchMethodException
* @throws NoSuchMethodException
*/
private Method matchMethod(Class oc, String methodName, Class[] pcs
) throws NoSuchMethodException, SecurityException {
try {
Method method = oc.getDeclaredMethod(methodName, pcs);
return method;
} catch (NoSuchMethodException e) {
Method[] ms = oc.getDeclaredMethods();
aa:for (int i = 0; i < ms.length; i++) {
if (ms[i].getName().equals(methodName)) {
Class[] pts = ms[i].getParameterTypes();
if (pts.length == pcs.length) {
for (int j = 0; j < pts.length; j++) {
if (!pts[j].isAssignableFrom(pcs[j])) {
break aa;
}
}
return ms[i];
}
}
}
throw new NoSuchMethodException();
}
} /**
* 新启线程后台调用给定方法更新缓存中数据据
* @param o
* @param methodName
* @param parameters
* @param key
*/
private void daemonInvoke(Object o, String methodName,Object[] parameters, String key) {
if (!threadKeys.contains(key)) {
InvokeThread t = new InvokeThread(o, methodName, parameters, key);
t.start();
}
}
 /**
* 些类存放方法的主调对像,名称及参数数组
* @author hiya
*
*/
public class MethodInfo {
private Object o;
private String methodName;
private Object[] parameters;
public MethodInfo(Object o, String methodName,Object[] parameters) {
this.o = o;
this.methodName = methodName;
this.parameters = parameters;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Object getO() {
return o;
}
public void setO(Object o) {
this.o = o;
}
public Object[] getParameters() {
return parameters;
}
public void setParameters(Object[] parameters) {
this.parameters = parameters;
} public String toString() {
StringBuffer str = new StringBuffer(methodName);
if (parameters != null) {
str.append("(");
for (int i = 0; i < parameters.length; i++) {
if (parameters[i] instanceof Object[]) {
str.append(Arrays.toString((Object[])parameters[i])).append(",");
} else {
str.append(parameters[i]).append(",");
}
}
str.append(")");
}
return str.toString();
}
}
    /**
* 线程调用方法
* @author hiya
*
*/
private class InvokeThread extends Thread {
private Object o;
private String methodName;
private Object[] parameters;
private String key;
public InvokeThread(Object o, String methodName,Object[] parameters, String key) {
this.o = o;
this.methodName = methodName;
this.parameters = parameters;
this.key = key;
} public void run() {
threadKeys.add(key);
invoke(o, methodName, parameters, key);
threadKeys.remove(key);
}
} /**
* 移除缓存中的数据
* @param key
*/
public void removeCacheData(String key) {
cacheMap.remove(key);
} /**
* 移除所有缓存中的数据
*
*/
public void removeAllCacheData() {
cacheMap.clear();
} public String toString() {
StringBuffer sb = new StringBuffer("************************ ");
sb.append("正在更新的缓存数据: ");
for (int i = 0; i < threadKeys.size(); i++) {
sb.append(threadKeys.get(i)).append(" ");
}
sb.append("当前缓存大小:").append(cacheMap.size()).append(" ");
sb.append("************************");
return sb.toString();
} }

实际使用:

package atest.hiyaCache;

//import javax.swing.text.Document;

import atest.hiyaCache.CacheOperation.MethodInfo;

public class CacheExec {

    /**
* @param args
*/
public static void main(String[] args) {// String province = request.getParameter("province");
// String city= request.getParameter("city");
// String county= request.getParameter("county");
// Document doc = XMLBuilder.buildLatelyKeyword(kwm.latelyKeyword(province, city, county));
// out.write(doc); String province = "Jiangsu ";
String city= "Nanjing ";
String county= "Jiangning";
CacheOperation co = CacheOperation.getInstance();
// MethodInfo mi = co.new MethodInfo(kwm, "latelyKeyword", new Object[]{province, city, county});
// Document doc = (Document )co.getCacheData(XMLBuilder.class,"buildLatelyKeyword",new Object[]{mi}, 120000, 0);
// out.write(doc);
while (true){
// chf@tsinghua.org.cn
MethodInfo mi = co.new MethodInfo(AddrDetail.class, "latelyKeyword", new Object[]{province, city, county});
// 120000 毫秒(2分钟)更新缓存
String aa = (String)co.getCacheData(AddrDetail.class,"buildCache",new Object[]{mi}, 120000, 5);
System.out.println("CacheExec:main=" + aa);
} } }

当缓存次数超过5时,重新执行。看一下执行结果。

AddrDetail.latelyKeyword=Jiangsu Nanjing Jiangning
AddrDetail.buildCache=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
AddrDetail.latelyKeyword=Jiangsu Nanjing Jiangning
AddrDetail.buildCache=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
CacheExec:main=Jiangsu Nanjing Jiangning
AddrDetail.latelyKeyword=Jiangsu Nanjing Jiangning
AddrDetail.buildCache=Jiangsu Nanjing Jiangning

  大数据量的缓存肯定还是要保存到文件,这个时候光用JDK来实现就比较复杂了,这里当然要用到第三方开源框架来实现了,常用的有Oscache,Ehcache,Jcache,Jbosscache等等很多,推荐还是Ehcache与Oscache,hibernate采用了Ehcache做为其缓存机制默认实现,Oscache没深入研究,但是Ibatis推荐的缓存为这个。

   为什么要缓存,无非就是节省访问时间已经大并发量带来的访问上资源的消耗,这个资源有软资源和硬资源,做java的几乎每天都在有意识或者无意识的跟缓存打交道,最常见的缓存,Connection Pool,还有IOC其实也算一个。

  缓存用的好能提高性能,用的不好反而会急剧的降低产品的性能,就拿hibernate来说,hibernate性能肯定不如jdbc,但是缓存用的好的话增删改查的性能相差无几,hibernate缓存最核心的部分个人觉得在于对象的有效性,缓存的命中率越高意味着性能越高,命中率跟缓存对象的有效性息息相关,如何保证对象有效这个很难,也很有搞头,如果缓存中对象有效性很差,其性能甚至会低于不用缓存,因为缓存本身就会耗性能跟资源,缓存的对象很多都很快失效了无疑得不偿失,还有缓存的深度也有讲究,这个深度是指从页面到数据库,显然是页面缓存的性能最好,因为调用页面缓存消耗的资源最少,当然现实中是不可能有太多页面缓存的。

Java 缓存技术的更多相关文章

  1. (转)java缓存技术,记录

    http://blog.csdn.net/madun/article/details/8569860 最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇 ...

  2. JAVA缓存技术之EhCache

    最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇,暂作保存,后面如果有用到可以参考.此为转贴,帖子来处:http://cogipard.info/ar ...

  3. JAVA缓存技术之EhCache(转)

    最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇,暂作保存,后面如果有用到可以参考.此为转贴,帖子来处:http://cogipard.info/ar ...

  4. JAVA缓存技术

    介绍 JNotify:http://jnotify.sourceforge.net/,通过JNI技术,让Java代码可以实时的监控制定文件夹内文件的变动信息,支持Linux/Windows/MacOS ...

  5. java缓存技术(转)

    最近在做java缓存,了解了一下.以下仅是对map对方式讨论.没有对点阵图阵讨论.作缓存要做以下2点: 1:清理及更新缓存时机的处理:   . 虚拟机内存不足,清理缓存   .. 缓存时间超时,或访问 ...

  6. java缓存技术的介绍

    一.什么是缓存1.Cache是高速缓冲存储器 一种特殊的存储器子系统,其中复制了频繁使用的数据以利于快速访问2.凡是位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之 ...

  7. 干货|java缓存技术详解

    一.缓存是什么? 请点击此处输入图片描述 Cache ①高速缓冲存储器,其中复制了频繁使用的数据以利于快速访问. ②位于速度相差较大的两种硬件/软件之间,用于协调两者数据传输速度差异的结构 二.缓存有 ...

  8. Java 缓存技术之 ehcache

    1. EHCache 的特点,是一个纯Java ,过程中(也可以理解成插入式)缓存实现,单独安装Ehcache ,需把ehcache-X.X.jar 和相关类库方到classpath中.如项目已安装了 ...

  9. Java缓存技术有哪些

    我们用ehcache在本地,分布式用redis和memcache,各有各的好处,现在企业都是应用很多种中间件供俺们码农选择.

随机推荐

  1. 二叉树结构 codevs 1029 遍历问题

    codevs 1029 遍历问题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 我们都很熟悉二叉树的前序.中序.后序遍 ...

  2. poj2387 Til the Cows Come Home 最短路径dijkstra算法

    Description Bessie is out in the field and wants to get back to the barn to get as much sleep as pos ...

  3. HDU 4990 Ordered Subsequence --数据结构优化DP

    题意:给一串数字,问长度为m的严格上升子序列有多少个 解法:首先可以离散化为10000以内,再进行dp,令dp[i][j]为以第i个元素结尾的长度为j的上升子序列的个数, 则有dp[i][j] = S ...

  4. UVALive 6257 Chemist's vows --一道题的三种解法(模拟,DFS,DP)

    题意:给一个元素周期表的元素符号(114种),再给一个串,问这个串能否有这些元素符号组成(全为小写). 解法1:动态规划 定义:dp[i]表示到 i 这个字符为止,能否有元素周期表里的符号构成. 则有 ...

  5. Unity2D之让土豆人动起来

    Unity2D功能 Unity3D最新的4.3版本,其中最大的新功能就是这个2D工具了.我这里简单介绍一下这个2D工具是怎样使用的. 首先,在我们创建项目的时候,面板上面多了一个2d和3d的选择,这两 ...

  6. AutoIT 实现Firefox上传文件

    Firefox浏览器文件上传代码如下: ;upload file Func _UploadFile($file) AutoItSetOption("WinTitleMatchMode&quo ...

  7. Sql注入截取字符串常用函数

    在sql注入中,往往会用到截取字符串的问题,例如不回显的情况下进行的注入,也成为盲注,这种情况下往往需要一个一个字符的去猜解,过程中需要用到截取字符串.本文中主要列举三个函数和该函数注入过程中的一些用 ...

  8. htacess 上传

    .创建一个.htaccess文件,内容如下: <FilesMatch "_php.gif"> SetHandler application/x-httpd-php &l ...

  9. Android优化—— Google 发布 Android 性能优化典范

    阅读目录 0)Render Performance 1)Understanding Overdraw 2)Understanding VSYNC 3)Tool:Profile GPU Renderin ...

  10. Java Web利用POI导出Excel简单例子

    采用Spring mvc架构: Controller层代码如下 @Controller public class StudentExportController{ @Autowired private ...