admin 管理员组

文章数量: 887021


2024年1月16日发(作者:gzip在线压缩)

JAVA缓存

1 Cache类

2 CacheManager类

JAVA缓存有两种:

一、文件缓存,是指把数据存储在磁盘上,可以XML格式,也可以序列化文件DAT格式还是其它文件格式。

二、内存缓存,也就是实现一个类中静态Map,对这个Map进行常规的增删查。

其代码如下:

JAVA缓存 - Cache类

public class Cache {

private String key;//缓存ID

private Object value;//缓存数据

private long timeOut;//更新时间

private boolean expired; //是否终止

public Cache() {

super();

}

public Cache(String key, Object value, long timeOut, boolean expired) {

= key;

= value;

t = timeOut;

d = expired;

}

public String getKey() {

return key;

}

public long getTimeOut() {

return timeOut;

}

public Object getValue() {

return value;

}

public void setKey(String string) {

key = string;

}

public void setTimeOut(long l) {

timeOut = l;

}

public void setValue(Object object) {

value = object;

}

public booleanisExpired() {

return expired;

}

public void setExpired(boolean b) {

expired = b;

}

}

//测试类,

class Test {

public static void main(String[] args) {

n(pleFlag("alksd"));

// he("abc", new Cache());

// he("def", new Cache());

// he("ccc", new Cache());

// nly("");

// Cache c = new Cache();

// for (int i = 0; i < 10; i++) {

// he("" + i, c);

// }

// he("aaaaaaaa", c);

// he("abchcy;alskd", c);

// he("cccccccc", c);

// he("abcoqiwhcy", c);

// n("删除前的大小:"+heSize());

// heAllkey();

// ll("aaaa");

// n("删除后的大小:"+heSize());

// heAllkey();

}

}

JAVA缓存 - CacheManager类

public class CacheManager {

private static HashMapcacheMap = new HashMap();

//单实例构造方法

private CacheManager() {

super();

}

//获取布尔值的缓存

public static booleangetSimpleFlag(String key){

try{

return (Boolean) (key);

}catch(NullPointerException e){

return false;

}

}

public static long getServerStartdt(String key){

try {

return (Long)(key);

} catch (Exception ex) {

return 0;

}

}

//设置布尔值的缓存

public synchronized static booleansetSimpleFlag(String key,boolean flag){

if (flag &&getSimpleFlag(key)) {//假如为真不允许被覆盖

return false;

}else{

(key, flag);

return true;

}

}

public synchronized static booleansetSimpleFlag(String key,longserverbegrundt){

if ((key) == null) {

(key,serverbegrundt);

return true;

}else{

return false;

}

}

//得到缓存。同步静态方法

private synchronized static Cache getCache(String key) {

return (Cache) (key);

}

//判断是否存在一个缓存

private synchronized static booleanhasCache(String key) {

return nsKey(key);

}

//清除所有缓存

public synchronized static void clearAll() {

();

}

//清除某一类特定缓存,通过遍历HASHMAP下的所有对象,来判断它的KEY与传入的TYPE是否匹配

public synchronized static void clearAll(String type) {

Iterator i = et().iterator();

String key;

ArrayListarr = new ArrayList();

try {

while (t()) {

entry = () ();

key = (String) ();

if (With(type)) { //如果匹配则删除掉

(key);

}

}

for (int k = 0; k <(); k++) {

clearOnly((k));

}

} catch (Exception ex) {

tackTrace();

}

}

//清除指定的缓存

public synchronized static void clearOnly(String key) {

(key);

}

//载入缓存

public synchronized static void putCache(String key, Cache obj) {

(key, obj);

}

//获取缓存信息

public static Cache getCacheInfo(String key) {

if (hasCache(key)) {

Cache cache = getCache(key);

if (cacheExpired(cache)) { //调用判断是否终止方法

ired(true);

}

return cache;

}else

return null;

}

//载入缓存信息

public static void putCacheInfo(String key, Cache obj, long dt,boolean expired) {

Cache cache = new Cache();

(key);

eOut(dt + tTimeMillis()); //设置多久后更新缓存

ue(obj);

ired(expired); //缓存默认载入时,终止状态为FALSE

(key, cache);

}

//重写载入缓存信息方法

public static void putCacheInfo(String key,Cacheobj,longdt){

Cache cache = new Cache();

(key);

eOut(dt+tTimeMillis());

ue(obj);

ired(false);

(key,cache);

}

//判断缓存是否终止

public static booleancacheExpired(Cache cache) {

if (null == cache) { //传入的缓存不存在

return false;

}

long nowDt = tTimeMillis(); //系统当前的毫秒数

long cacheDt = eOut(); //缓存内的过期毫秒数

if (cacheDt<= 0||cacheDt>nowDt) { //过期时间小于等于零时,或者过期时间大于当前时间时,则为FALSE

return false;

} else { //大于过期时间 即过期

return true;

}

}

//获取缓存中的大小

public static intgetCacheSize() {

return ();

}

//获取指定的类型的大小

public static intgetCacheSize(String type) {

int k = 0;

Iterator i = et().iterator();

String key;

try {

while (t()) {

entry = () ();

key = (String) ();

if (f(type) != -1) { //如果匹配则删除掉

k++;

}

}

} catch (Exception ex) {

tackTrace();

}

return k;

}

//获取缓存对象中的所有键值名称

public static ArrayListgetCacheAllkey() {

ArrayList a = new ArrayList();

try {

Iterator i = et().iterator();

while (t()) {

entry = () ();

((String) ());

}

} catch (Exception ex) {} finally {

return a;

}

}

//获取缓存对象中指定类型 的键值名称

public static ArrayListgetCacheListkey(String type) {

ArrayList a = new ArrayList();

String key;

try {

Iterator i = et().iterator();

while (t()) {

entry = () ();

key = (String) ();

if (f(type) != -1) {

(key);

}

}

} catch (Exception ex) {} finally {

return a;

}

}

}

2007-09-29

简单LRU算法实现缓存

最简单的LRU算法实现,就是利用jdk的LinkedHashMap,removeEldestEntry()方法即可,如下所示:

java 代码

1. import ist;

覆写其中的

2.

3.

4.

5.

6.

7.

8.

9.

import tion;

import HashMap;

import ;

import antLock;

import ;

/**

10. * 类说明:利用LinkedHashMap实现简单的缓存, 必须实现removeEldestEntry方法,具体参见JDK文档

11. *

12. * @author dennis

13. *

14. * @param

15. * @param

16. */

17. public class LRULinkedHashMap extends LinkedHashMap {

18. private final int maxCapacity;

19.

20. private static final float DEFAULT_LOAD_FACTOR = 0.75f;

21.

22. private final Lock lock = new ReentrantLock();

23.

24. public LRULinkedHashMap(int maxCapacity) {

25. super(maxCapacity, DEFAULT_LOAD_FACTOR, true);

26. acity = maxCapacity;

27. }

28.

29. @Override

30. protected boolean removeEldestEntry( eldest) {

31. return size() > maxCapacity;

32. }

33. @Override

34. public boolean containsKey(Object key) {

35. try {

36. ();

37. return nsKey(key);

38. } finally {

39. ();

40. }

41. }

42.

43.

44. @Override

45. public V get(Object key) {

46. try {

47. ();

48. return (key);

49. } finally {

50. ();

51. }

52. }

53.

54. @Override

55. public V put(K key, V value) {

56. try {

57. ();

58. return (key, value);

59. } finally {

60. ();

61. }

62. }

63.

64. public int size() {

65. try {

66. ();

67. return ();

68. } finally {

69. ();

70. }

71. }

72.

73. public void clear() {

74. try {

75. ();

76. ();

77. } finally {

78. ();

79. }

80. }

81.

82. public Collection<> getAll() {

83. try {

84. ();

85. return new ArrayList<>(et());

86. } finally {

87. ();

88. }

89. }

90. }

91.

如果你去看LinkedHashMap的源码可知,LRU算法是通过双向链表来实现,当某个位置被命中,通过调整链表的指向将该位置调整到头位置,新加入的内容直接放在链表头,如此一来,最近被命中的内容就向链表头移动,需要替换时,链表最后的位置就是最近最少使用的位置。

LRU算法还可以通过计数来实现,缓存存储的位置附带一个计数器,当命中时将计数器加1,替换时就查找计数最小的位置并替换,结合访问时间戳来实现。这种算法比较适合缓存数据量较小的场景,显然,遍历查找计数最小位置的时间复杂度为O(n)。我实现了一个,结合了访问时间戳,当最小计数大于 MINI_ACESS时,就移除最久没有被访问的项:

java 代码

1. import izable;

2. import ist;

3. import tion;

4. import p;

5. import or;

6. import ;

7. import ;

8. import Integer;

9. import Long;

10. import ;

11. import antLock;

12.

13. /**

14. *

15. * @author dennis

16. * 类说明:当缓存数目不多时,才用缓存计数的传统LRU算法

17. * @param

18. * @param

19. */

20. public class LRUCache implements Serializable {

21.

22. private static final int DEFAULT_CAPACITY = 100;

23.

24. protected Map map;

25.

26. private final Lock lock = new ReentrantLock();

27.

28. private final transient int maxCapacity;

29.

30. private static int MINI_ACCESS = 10;

31.

32. public LRUCache() {

33. this(DEFAULT_CAPACITY);

34. }

35.

36. public LRUCache(int capacity) {

37. if (capacity <= 0)

38. throw new RuntimeException("缓存容量不得小于0");

39. acity = capacity;

40. = new HashMap(maxCapacity);

41. }

42.

43. public boolean ContainsKey(K key) {

44. try {

45. ();

46. return nsKey(key);

47. } finally {

48. ();

49. }

50. }

51.

52. public V put(K key, V value) {

53. try {

54. ();

55. if ((() > maxCapacity - 1) && !nsKey(key)) {

56. // n("开始");

57. Set<> entries = et();

58. removeRencentlyLeastAccess(entries);

59. }

60. ValueEntry valueEntry = (key, new ValueEntry(value));

61. if (valueEntry != null)

62. return ;

63. else

64. return null;

65. } finally {

66. ();

67. }

68. }

69.

70. /**

71. * 移除最近最少访问

72. */

73. protected void removeRencentlyLeastAccess(

74. Set<> entries) {

75. // 最小使用次数

76. int least = 0;

77. // 最久没有被访问

78. long earliest = 0;

79. K toBeRemovedByCount = null;

80. K toBeRemovedByTime = null;

81. Iterator<> it = or();

82. if (t()) {

83. valueEntry = ();

84. least = ue().();

85. toBeRemovedByCount = ();

86. earliest = ue().();

87. toBeRemovedByTime = ();

88. }

89. while (t()) {

90. valueEntry = ();

91. if (ue().() < least) {

92. least = ue().();

93. toBeRemovedByCount = ();

94. }

95. if (ue().() < earliest) {

96. earliest = ue().();

97. toBeRemovedByTime = ();

98. }

99. }

100. // n("remove:" + toBeRemoved);

101. // 如果最少使用次数大于MINI_ACCESS,那么移除访问时间最早的项(也就是最久没有被访问的项)

102. if (least > MINI_ACCESS) {

103. (toBeRemovedByTime);

104. } else {

105. (toBeRemovedByCount);

106. }

107. }

108.

109. public V get(K key) {

110. try {

111. ();

112. V value = null;

113. ValueEntry valueEntry = (key);

114. if (valueEntry != null) {

115. // 更新访问时间戳

116. LastAccess();

117. // 更新访问次数

118. entAndGet();

119. value = ;

120. }

121. return value;

122. } finally {

123. ();

124. }

125. }

126.

127. public void clear() {

128. try {

129. ();

130. ();

131. } finally {

132. ();

133. }

134. }

135.

136. public int size() {

137. try {

138. ();

139. return ();

140. } finally {

141. ();

142. }

143. }

144.

145. public Collection<> getAll() {

146. try {

147. ();

148. Set keys = ();

149. Map tmp = new HashMap();

150. for (K key : keys) {

151. (key, (key).value);

152. }

153. return new ArrayList<>(et());

154. } finally {

155. ();

156. }

157. }

158.

159. class ValueEntry implements Serializable {

160. private V value;

161.

162. private AtomicInteger count;

163.

164. private AtomicLong lastAccess;

165.

166. public ValueEntry(V value) {

167. = value;

168. = new AtomicInteger(0);

169. lastAccess = new AtomicLong(me());

170. }

171.

172. public void updateLastAccess() {

173. (me());

174. }

175.

176. }

177. }

2008-04-07

LRU Cache

看了下RU(Least Recently Used ,最近最少使用),可以使用LinkedHashMap实现,到是蛮简单的.LinkedHashMap会将get或是put的数据置于底端.

重写removeEldestEntry()可以设定根据size来调整cache的数量.

Java代码

1. import tion;

2. import HashMap;

3. import ;

4.

5. /**

6. * This class uses the LinkedHashMap to build LRU cache.

7. * User can define the cache size.

8. */

9. public class LRUCache

10. {

11. int cacheSize = 0;

12. float loadFactor = 0.75f; //default

13. LinkedHashMap map;

14.

15. public LRUCache(int cacheSize)

16. {

17. ize = cacheSize;

18. map = new LinkedHashMap(cacheSize, loadFactor, true)

19. {

20. protected boolean removeEldestEntry( eldest)

21. {

22. return size() > ize;

23. //return false;

24. }

25. };

26. }

27.

28. public synchronized void clear()

29. {

30. ();

31. }

32.

33. public synchronized Object get(Object key)

34. {

35. return (key);

36. }

37.

38. public synchronized void put(Object key, Object value)

39. {

40. (

41. key,

42. value);

43. }

44.

45. public synchronized Object remove(Object key)

46. {

47. return (key);

48. }

49.

50. public synchronized int size()

51. {

52. return ();

53. }

54.

55. public synchronized Collection values()

56. {

57. return ();

58. }

59.

60. public static void main(String []args)

61. {

62. // testing

63. int size = 3;

64. LRUCache cache = new LRUCache(size);

65. (new Integer("1"), "1");

66. (new Integer("2"), "2");

67. (new Integer("3"), "3");

68.

69. String value = (String)(new Integer(1));

70. n(value);

71. n("Testing ...");

72.

73. Object[] values = ().toArray();

74. for (int i = 0; i < ; i++)

75. {

76. value = (String)values[i];

77. n(value);

78. }

79. }

80. }

LRU缓存应用一例

首先,来看看LRU的定义: Least recently used. 可以理解为,最少使用的被淘汰。在网上发现了这个LRUCache 类及文章

《基于双链表实现缓存策略之LRU实现》,正好站内有一个搜索

《ACM AND JAVA》/cwbwebhome/

需要缓存,应用了一把,这样就不需要每次搜索POJID都查询数据库。先凑合着用了。

package ;

import ble;

.*;

public class LRUCache {

private intcacheSize;

private Hashtable nodes;//缓存容器

private intcurrentSize;

private CacheNode first;//链表头

private CacheNode last;//链表尾

private static LRUCache instance=new LRUCache(1000);

/**

* 链表节点

* @author Administrator

*

*/

class CacheNode {

CacheNodeprev;//前一节点

CacheNode next;//后一节点

Object value;//值

Object key;//键

CacheNode() {

}

}

private LRUCache(int i) {

currentSize = 0;

cacheSize = i;

nodes = new Hashtable(i);//缓存容器

ResultSetRst=null;

DbTransdb=new DbTrans();

try{

Rst=eQuery("select File_name,Article_type from Article where type_id=17");

String f_name=null;

String a_type=null;

while(()){//将数据库中的记录全部取出,缓存。

a_type=ing("Article_type");

f_name=ing("File_name");

put(a_type,f_name);

}

if(Rst!=null) ();

if(db!=null) ();

}catch(SQLException e){

n(ng());

}

}

public static LRUCachegetInstance(){

return instance;

}

/**

* 获取缓存中对象

* @param key

* @return

*/

public Object get(Object key) {

CacheNode node = (CacheNode) (key);

if (node != null) {

moveToHead(node);

return ;

} else {

return null;

}

}

/**

* 添加缓存

* @param key

* @param value

*/

public void put(Object key, Object value) {

CacheNode node = (CacheNode) (key);

if (node == null) {

//缓存容器是否已经超过大小.

if (currentSize>= cacheSize) {

if (last != null)//将最少使用的删除

();

removeLast();

} else {

currentSize++;

}

node = new CacheNode();

}

= value;

= key;

//将最新使用的节点放到链表头,表示最新使用的.

moveToHead(node);

(key, node);

}

/**

* 将缓存删除

* @param key

* @return

*/

public Object remove(Object key) {

CacheNode node = (CacheNode) (key);

if (node != null) {

if ( != null) {

= ;

}

if ( != null) {

= ;

}

if (last == node)

last = ;

if (first == node)

first = ;

}

return node;

}

public void clear() {

first = null;

last = null;

}

/**

* 删除链表尾部节点

* 表示 删除最少使用的缓存对象

*/

private void removeLast() {

//链表尾不为空,则将链表尾指向null. 删除连表尾(删除最少使用的缓存对象)

if (last != null) {

if ( != null)

= null;

else

first = null;

last = ;

}

}

/**

* 移动到链表头,表示这个节点是最新使用过的

* @param node

*/

private void moveToHead(CacheNode node) {

if (node == first)

return;

if ( != null)

= ;

if ( != null)

= ;

if (last == node)

last = ;

if (first != null) {

= first;

= node;

}

first = node;

= null;

if (last == null)

last = first;

}

}

有些不满意之处,主要是缓存大小不好确定,暂定为1000, 以后题目多了,要重新编译源文件。(缓存大小最好写在一个配置

文件中)

最后看一下JSP文件:,从提交页面获取POJID,从缓存中取数据。

<%@ page import="he" %>

<%@ page import="r" %>

<%@ page import="n" %>

<%@ page import="he" %>

<%

String s=ameter("s");

String toPage="";

String pattern = "d{1,5}";

n(s);

if(s==null||()==0) {

toPage="";

}else {

Pattern p = e(pattern);

Matcher m = r(s);

boolean b = s();

n(b);

if(!b){

toPage="";

}else{

LRUCache cache=tance();

String f_name=(String)(s);

if(f_name!=null)

toPage=f_name;

else

toPage="";

}

}

direct(toPage);

%>


本文标签: 缓存 实现 链表 位置 使用