java緩存技術_java緩存技術

最近在做java緩存,了解了一下.

以下僅是對map對方式討論。沒有對點陣圖陣討論。

作緩存要做以下2點:

1:清理及更新緩存時機的處理:

. 虛擬機內存不足,清理緩存

.. 緩存時間超時,或訪問次數超出, 啟動線程更新

2:類和方法的反射 (線程嵌套調用)

reflect.invoke的使用。

代碼如下:

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) {

// TODO 自動生成されたメソッド?スタブ

//??????? 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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259678.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259678.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259678.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

xss challenge 解題思路(1-3)

challenge1: 用很基本的方法即可&#xff0c;截圖如下&#xff1a; 提交后成功彈窗&#xff0c;完成。 challenge2 這次我們發現我們輸入的內容被放入value”“ 中&#xff0c;所以需要將前面的結構閉合&#xff0c;構造如下&#xff1a; "><script>alert(docume…

賓得準餅干廣角鏡頭DA15

DA15的掛機效果圖&#xff0c;感覺還是超級的小&#xff0c;是最小的廣角鏡頭了&#xff1a; 主要特點1. 超廣視角當安裝在賓得數碼單反相機上時&#xff0c;這款全新的鏡頭提供相當于35mm膠片規格的約23mm畫面視角&#xff0c;可使拍攝者拍攝出獨特的誘人影像和超廣角鏡頭獨有…

無限“遞歸”的python程序

如果一個函數直接或者間接調用了自己&#xff0c;那么就形成了遞歸&#xff08;recursion&#xff09;&#xff0c;比如斐波那契數列的一個實現 def fib(n):if n < 2:return 1else:return fib(n - 1) fib(n - 2) 遞歸一定要有結束條件&#xff0c;否則就形成了死循環&#…

java slf4j_SLF4J 使用手冊

原文鏈接 譯者&#xff1a;zivyuJava的簡單日志門面( Simple Logging Facade for Java SLF4J)作為一個簡單的門面或抽象&#xff0c;用來服務于各種各樣的日志框架&#xff0c;比如java.util.logging、logback和log4j。SLF4J允許最終用戶在部署時集成自己想要的日志框架。需要…

[譯]Java 垃圾回收介紹

說明&#xff1a;這篇文章來翻譯來自于Javapapers 的Java Garbage Collection Introduction 在Java中&#xff0c;對象內存空間的分配與回收是由JVM中的垃圾回收進程自動完成的。和C語言不一樣的是&#xff0c;開發中不需要在Java中寫垃圾回收代碼。這也是使Java更加流行而且幫…

打印三角形

直角三角形 #include<iostream> using namespace std; int main() { int i,j; for(i1;i<10;i) {for(j1;j<i;j) cout<<"*"; cout<<endl; } } ———————————————————————————…

Linux基礎入門學習筆記之二

第三節 用戶及文件權限管理 Linux用戶管理 Linux是可以實現多用戶登錄的操作系統 查看用戶who命令用于查看用戶 shiyanlou是當前登錄用戶的用戶名 pts/0中pts表示偽終端&#xff0c;后面的數字表示偽終端的序號。 后面是當前偽終端啟動時間 創建用戶創建用戶需要root權限&#…

java選填_java基礎填空選擇題

Core Java試題選擇填空題&#xff1a;全部為多選題&#xff0c;只有全部正確才能得分。1. 編譯java程序的命令是__B_;運行java程序的命令是____A____;產生java文擋的命令是_____D___;查詢java類型是否是serializable類型的命令是___C_____;產生java安全策略文件的命令是____E__…

這幾天有django和python做了一個多用戶博客系統(可選擇模板) 沒完成,先分享下...

這個TBlog已經全新改版了&#xff0c;更名為UUBlog 新版地址&#xff1a; 用Python和Django實現多用戶博客系統——UUBlog 斷斷續續2周時間吧&#xff0c;用django做了一個多用戶博客系統&#xff0c;現在還沒有做完&#xff0c;做分享下,以后等完善了再慢慢說 做的時候房展了博…

Hibernate的generator屬性

本文講述Hibernate的generator屬性的意義。Generator屬性有7種class&#xff0c;本文簡略描述了這7種class的意義和用法。[xhtml] view plaincopy <class name"onlyfun.caterpillar.User" table"USER"> <id name"id" type"stri…

java 對象池 博客_Java對象池技術的原理及其實現的小結

一起學習Java對象的生命周期大致包括三個階段&#xff1a;對象的創建&#xff0c;對象的使用&#xff0c;對象的清除。因此&#xff0c;對象的生命周期長度可用如下的表達式表示&#xff1a;T T1 T2 T3。其中T1表示對象的創建時間&#xff0c;T2表示對象的使用時間&#xff0c…

matlab中gatbx工具箱的添加

1. 從http://crystalgate.shef.ac.uk/code/下載工具箱壓縮包gatbx.zip 2. 解壓gatbx.zip&#xff0c;將其子文件夾genetic放在matlab安裝目錄toolbox文件夾下 3. 在matlab主窗口選擇File -> Set Path&#xff0c; 單擊"Add Folder"按鈕&#xff0c;找到工具箱所在…

C#與數據庫訪問技術總結(十七)

使用DataSet對象訪問數據庫 當對DataSet對象進行操作時&#xff0c;DataSet對象會產生副本&#xff0c;所以對DataSet里的數據進行編輯操作不會直接對數據庫產生影響&#xff0c;而是將DataRow的狀態設置為added、deleted或changed&#xff0c;最終的更新數據源動作將通過DataA…

MySQL數據高級查詢之連接查詢、聯合查詢、子查詢

2019獨角獸企業重金招聘Python工程師標準>>> 一、連接查詢 連接查詢: 將多張表(>2)進行記錄的連接(按照某個指定的條件進行數據拼接)。 連接查詢的意義: 在用戶查看數據的時候,需要顯示的數據來自多張表. 連接查詢: join, 使用方式: 左表 join 右表&#xff1b;左…

Oracle11g解鎖報錯SP2-0306-選項無效

普通用戶登錄isqlplus: (一)在瀏覽器中輸入URL &#xff08;http://localhost:5560/isqlplus&#xff09;。顯示登錄界面 這里只能用普通用戶進行登錄&#xff0c;因為要用sys登錄&#xff0c;必須用sys的DBA身份登錄。所以用普通用戶SCOTT&#xff0c;但是還未解鎖 問題:SP2-0…

java web登錄action_JavaWeb中登陸功能

首先我們要JavaWeb登陸的基本流程&#xff1a;JSP頁面發送請求——>Servlet——>Servlet通過調用方法從數據庫中得到數據并將結果返回頁面我們先建立三個jsp頁面&#xff0c;包括login.jsp(登陸頁面)、index.jsp(顯示登陸成功后的信息)、error.jsp(登錄失敗的頁面)&#…

Android Download Manager用法大全

http://www.trinea.cn/android/android-downloadmanager/ http://www.trinea.cn/android/android-downloadmanager-pro/轉載于:https://www.cnblogs.com/soaringEveryday/articles/4135204.html

Chrome瀏覽器無法觀看視頻,一直提示“adobe flash player 已過期” ?

很多新用戶在安裝了Chrome瀏覽器或者更新過的的時候&#xff0c;經常提示“ adobe flash player 已過期”的問題&#xff0c;反復提示&#xff0c;導致無法觀看視頻。于是從網上也找了很多辦法都沒有解決。這里給大家提供一個最完美的解決方案。經親自測試&#xff0c;完美解決…

關于JVM的垃圾回收GC的一些記錄

目錄 一、JVM內存區域劃分 二、從一個基本問題開始引入垃圾回收 三、GC作用的區域 三、如何確定一個對象是否可以被當成垃圾進行回收 &#xff08;1&#xff09;引用計數法 &#xff08;2&#xff09;可達性分析算法 &#xff08;3&#xff09;引用的類型 &#xff08;3…

同步與互斥

有數據交互的進程之間的關系主要有兩種,同步與互斥.所謂互斥,是指在不同進程之間的若干程序片斷,當某個進程運行其中一個程序片段時,其它進程就不能運行它們之中的任一程序片段,只能等到該進程運行完這個程序片段后才可以運行.所謂同步,是指在不同進程之間的若干程序片斷,它們的…