前言
本次分享探討java平臺(tái)的本地緩存,是指占用JVM的heap區(qū)域來(lái)緩沖存儲(chǔ)數(shù)據(jù)的緩存組件。
一、本地緩存應(yīng)用場(chǎng)景
localcache有著極大的性能優(yōu)勢(shì):
1. 單機(jī)情況下適當(dāng)使用localcache會(huì)使應(yīng)用的性能得到很大的提升。
2. 集群環(huán)境下對(duì)于敏感性要求不高的數(shù)據(jù)可以使用localcache,只配置簡(jiǎn)單的失效機(jī)制來(lái)保證數(shù)據(jù)的相對(duì)一致性。
哪些數(shù)據(jù)可以存儲(chǔ)到本地緩存?
1.訪問(wèn)頻繁的數(shù)據(jù);
2.靜態(tài)基礎(chǔ)數(shù)據(jù)(長(zhǎng)時(shí)間內(nèi)不變的數(shù)據(jù));
3.相對(duì)靜態(tài)數(shù)據(jù)(短時(shí)間內(nèi)不變的數(shù)據(jù))。
二、java本地緩存標(biāo)準(zhǔn)
Java緩存新標(biāo)準(zhǔn)(javax.cache),這個(gè)標(biāo)準(zhǔn)由JSR107所提出,已經(jīng)被包含在Java EE 7中。
特性:
1.原子操作,跟java.util.ConcurrentMap類似
2.從緩存中讀取
3.寫入緩存
4.緩存事件監(jiān)聽器
5.?dāng)?shù)據(jù)統(tǒng)計(jì)
6.包含所有隔離(ioslation)級(jí)別的事務(wù)
7.緩存注解(annotations)
8.保存定義key和值類型的泛型緩存
9.引用保存(只適用于堆緩存)和值保存定義
但目前應(yīng)用不是很普遍。
三、java開源緩存框架
比較有名的本地緩存開源框架有:
1.EHCache
EHCache是一個(gè)純java的在進(jìn)程中的緩存,它具有以下特性:快速,簡(jiǎn)單,為Hibernate2.1充當(dāng)可插入的緩存,最小的依賴性,全面的文檔和測(cè)試。
BUG: 過(guò)期失效的緩存元素?zé)o法被GC掉,時(shí)間越長(zhǎng)緩存越多,內(nèi)存占用越大,導(dǎo)致內(nèi)存泄漏的概率越大。
2.OSCache
OSCache有以下特點(diǎn):緩存任何對(duì)象,你可以不受限制的緩存部分jsp頁(yè)面或HTTP請(qǐng)求,任何java對(duì)象都可以緩存。擁有全面的API--OSCache API給你全面的程序來(lái)控制所有的OSCache特性。永久緩存--緩存能隨意的寫入硬盤,因此允許昂貴的創(chuàng)建(expensive-to-create)數(shù)據(jù)來(lái)保持緩存,甚至能讓應(yīng)用重啟。支持集群--集群緩存數(shù)據(jù)能被單個(gè)的進(jìn)行參數(shù)配置,不需要修改代碼。緩存記錄的過(guò)期--你可以有最大限度的控制緩存對(duì)象的過(guò)期,包括可插入式的刷新策略(如果默認(rèn)性能不需要時(shí))。
3.JCache
Java緩存新標(biāo)準(zhǔn)(javax.cache)
4.cache4j
cache4j是一個(gè)有簡(jiǎn)單API與實(shí)現(xiàn)快速的Java對(duì)象緩存。它的特性包括:在內(nèi)存中進(jìn)行緩存,設(shè)計(jì)用于多線程環(huán)境,兩種實(shí)現(xiàn):同步與阻塞,多種緩存清除策略:LFU, LRU, FIFO,可使用強(qiáng)引用。
5.ShiftOne
ShiftOne Java Object Cache是一個(gè)執(zhí)行一系列嚴(yán)格的對(duì)象緩存策略的Java lib,就像一個(gè)輕量級(jí)的配置緩存工作狀態(tài)的框架。
6.WhirlyCache
Whirlycache是一個(gè)快速的、可配置的、存在于內(nèi)存中的對(duì)象的緩存。
四、LocalCache實(shí)現(xiàn)
1、LocalCache簡(jiǎn)介
LocalCache是一個(gè)精簡(jiǎn)版本地緩存組件,有以下特點(diǎn):
1. 有容量上限maxCapacity;
2. 緩存達(dá)到容量上限時(shí)基于LRU策略來(lái)移除緩存元素;
3. 緩存對(duì)象的生命周期(緩存失效時(shí)間)由調(diào)用方?jīng)Q定;
4. 緩存對(duì)象失效后,將會(huì)有定時(shí)清理線程來(lái)清理掉,不會(huì)導(dǎo)致內(nèi)存泄漏。
5. 性能比Ehcache稍強(qiáng)。
2、總體設(shè)計(jì)
LocalCache總體設(shè)計(jì):
1. 緩存元素 CacheElement;
2. 緩存容器 LRULinkedHashMap;
3. 緩存接口 Cache;
4. 緩存組件實(shí)現(xiàn) LocalCache。
3、詳細(xì)設(shè)計(jì)
1. CacheElement設(shè)計(jì)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/** * 緩存元素 * */ public class CacheElement { private Object key; private Object value; private long createTime; private long lifeTime; private int hitCount; public CacheElement() { } public CacheElement(Object key ,Object value) { this .key = key; this .value = value; this .createTime = System.currentTimeMillis(); } public Object getKey() { return key; } public void setKey(Object key) { this .key = key; } public Object getValue() { hitCount++; return value; } public void setValue(Object value) { this .value = value; } public long getCreateTime() { return createTime; } public void setCreateTime( long createTime) { this .createTime = createTime; } public int getHitCount() { return hitCount; } public void setHitCount( int hitCount) { this .hitCount = hitCount; } public long getLifeTime() { return lifeTime; } public void setLifeTime( long lifeTime) { this .lifeTime = lifeTime; } public boolean isExpired() { boolean isExpired = System.currentTimeMillis() - getCreateTime() > getLifeTime(); return isExpired; } /* * (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append("[ key=").append(key).append(", isExpired=").append(isExpired()) .append(", lifeTime=").append(lifeTime).append(", createTime=").append(createTime) .append(", hitCount=").append(hitCount) .append(", value=").append(value).append(" ]"); return sb.toString(); } /* * (non-Javadoc) * @see java.lang.Object#hashCode() */ public final int hashCode(){ if(null == key){ return "".hashCode(); } return this.key.hashCode(); } /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public final boolean equals(Object object) { if ((object == null ) || (!(object instanceof CacheElement))) { return false ; } CacheElement element = (CacheElement) object; if (( this .key == null ) || (element.getKey() == null )) { return false ; } return this .key.equals(element.getKey()); } } |
2. LRULinkedHashMap實(shí)現(xiàn)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
import java.util.LinkedHashMap; import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 實(shí)現(xiàn) LRU策略的 LinkedHashMap * * @param <K> * @param <V> */ public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> { protected static final long serialVersionUID = 2828675280716975892L; protected static final int DEFAULT_MAX_ENTRIES = 100 ; protected final int initialCapacity; protected final int maxCapacity; protected boolean enableRemoveEldestEntry = true ; //是否允許自動(dòng)移除比較舊的元素(添加元素時(shí)) protected static final float DEFAULT_LOAD_FACTOR = 0 .8f; protected final Lock lock = new ReentrantLock(); public LRULinkedHashMap( int initialCapacity) { this (initialCapacity, DEFAULT_MAX_ENTRIES); } public LRULinkedHashMap( int initialCapacity , int maxCapacity) { //set accessOrder=true, LRU super (initialCapacity, DEFAULT_LOAD_FACTOR, true ); this .initialCapacity = initialCapacity; this .maxCapacity = maxCapacity; } /* * (non-Javadoc) * @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry) */ protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) { return enableRemoveEldestEntry && ( size() > maxCapacity ); } /* * (non-Javadoc) * @see java.util.LinkedHashMap#get(java.lang.Object) */ public V get(Object key) { try { lock.lock(); return super.get(key); } finally { lock.unlock(); } } /* * (non-Javadoc) * @see java.util.HashMap#put(java.lang.Object, java.lang.Object) */ public V put(K key, V value) { try { lock.lock(); return super.put(key, value); } finally { lock.unlock(); } } /* * (non-Javadoc) * @see java.util.HashMap#remove(java.lang.Object) */ public V remove(Object key) { try { lock.lock(); return super.remove(key); } finally { lock.unlock(); } } /* * (non-Javadoc) * @see java.util.LinkedHashMap#clear() */ public void clear() { try { lock.lock(); super.clear(); } finally { lock.unlock(); } } /* * (non-Javadoc) * @see java.util.HashMap#keySet() */ public Set<K> keySet() { try { lock.lock(); return super .keySet(); } finally { lock.unlock(); } } public boolean isEnableRemoveEldestEntry() { return enableRemoveEldestEntry; } public void setEnableRemoveEldestEntry( boolean enableRemoveEldestEntry) { this .enableRemoveEldestEntry = enableRemoveEldestEntry; } public int getInitialCapacity() { return initialCapacity; } public int getMaxCapacity() { return maxCapacity; } } |
3. Cache接口設(shè)計(jì)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
/** * 緩存接口 * */ public interface Cache { /** * 獲取緩存 * @param key * @return */ public <T> T getCache(Object key); /** * 緩存對(duì)象 * @param key * @param value * @param milliSecond 緩存生命周期(毫秒) */ public void putCache(Object key, Object value ,Long milliSecond); /** * 緩存容器中是否包含 key * @param key * @return */ public boolean containsKey(Object key); /** * 緩存列表大小 * @return */ public int getSize(); /** * 是否啟用緩存 */ public boolean isEnabled(); /** * 啟用 或 停止 * @param enable */ public void setEnabled( boolean enabled); /** * 移除所有緩存 */ public void invalidateCaches(); /** * 移除 指定key緩存 * @param key */ public void invalidateCache(Object key); } |
4. LocalCache實(shí)現(xiàn)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
|
import java.util.Date; import java.util.Iterator; import java.util.Random; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 本地緩存組件 */ public class LocalCache implements Cache{ private Logger logger = LoggerFactory.getLogger( this .getClass()); private LRULinkedHashMap<Object, CacheElement> cacheMap; protected boolean initFlag = false ; //初始化標(biāo)識(shí) protected final long defaultLifeTime = 5 * 60 * 1000 ; //5分鐘 protected boolean warnLongerLifeTime = false ; protected final int DEFAULT_INITIAL_CAPACITY = 100 ; protected final int DEFAULT_MAX_CAPACITY = 100000 ; protected int initialCapacity = DEFAULT_INITIAL_CAPACITY; //初始化緩存容量 protected int maxCapacity = DEFAULT_MAX_CAPACITY; //最大緩存容量 protected int timeout = 20 ; //存取緩存操作響應(yīng)超時(shí)時(shí)間(毫秒數(shù)) private boolean enabled = true ; private Thread gcThread = null ; private String lastGCInfo = null ; //最后一次GC清理信息{ size, removeCount, time ,nowTime} private boolean logGCDetail = false ; //記錄gc清理細(xì)節(jié) private boolean enableGC = true ; //是否允許清理的緩存(添加元素時(shí)) private int gcMode = 0 ; //清理過(guò)期元素模式 { 0=迭代模式 ; 1=隨機(jī)模式 } private int gcIntervalTime = 2 * 60 * 1000 ; //間隔時(shí)間(分鐘) private boolean iterateScanAll = true ; //是否迭代掃描全部 private float gcFactor = 0 .5F; //清理百分比 private int maxIterateSize = DEFAULT_MAX_CAPACITY/ 2 ; //迭代模式下一次最大迭代數(shù)量 private volatile int iterateLastIndex = 0 ; //最后迭代下標(biāo) private int maxRandomTimes = 100 ; //隨機(jī)模式下最大隨機(jī)次數(shù) protected final static Random random = new Random(); private static LocalCache instance = new LocalCache(); public static LocalCache getInstance() { return instance; } private LocalCache(){ this .init(); } protected synchronized void init() { if (initFlag){ logger.warn( "init repeat." ); return ; } this .initCache(); this .startGCDaemonThread(); initFlag = true ; if (logger.isInfoEnabled()){ logger.info( "init -- OK" ); } } private void startGCDaemonThread(){ if (initFlag){ return ; } this .maxIterateSize = maxCapacity / 2 ; try { this .gcThread = new Thread() { public void run() { logger.info( "[" + (Thread.currentThread().getName()) + "]start..." ); //sleep try { Thread.sleep(getGcIntervalTime() < 30000 ? 30000 : getGcIntervalTime()); } catch (Exception e) { e.printStackTrace(); } while ( true ){ //gc gc(); //sleep try { Thread.sleep(getGcIntervalTime() < 30000 ? 30000 : getGcIntervalTime()); } catch (Exception e) { e.printStackTrace(); } } } }; this .gcThread.setName( "localCache-gcThread" ); this .gcThread.setDaemon( true ); this .gcThread.start(); if (logger.isInfoEnabled()){ logger.info( "startGCDaemonThread -- OK" ); } } catch (Exception e){ logger.error( "[localCache gc]DaemonThread -- error: " + e.getMessage(), e); } } private void initCache(){ if (initFlag){ return ; } initialCapacity = (initialCapacity <= 0 ? DEFAULT_INITIAL_CAPACITY : initialCapacity); maxCapacity = (maxCapacity < initialCapacity ? DEFAULT_MAX_CAPACITY : maxCapacity); cacheMap = new LRULinkedHashMap<Object, CacheElement>(initialCapacity ,maxCapacity); if (logger.isInfoEnabled()){ logger.info( "initCache -- OK" ); } } /* * (non-Javadoc) */ @SuppressWarnings("unchecked") public <T> T getCache(Object key) { if(!isEnabled()){ return null; } long st = System.currentTimeMillis(); T objValue = null; CacheElement cacheObj = cacheMap.get(key); if (isExpiredCache(cacheObj)) { cacheMap.remove(key); }else { objValue = (T) (cacheObj == null ? null : cacheObj.getValue()); } long et = System.currentTimeMillis(); if((et - st)>timeout){ if(this.logger.isWarnEnabled()){ this.logger.warn("getCache_timeout_" + (et - st) + "_[" + key + "]"); } } if(logger.isDebugEnabled()){ String message = ("get( " + key + ") return: " + objValue); logger.debug(message); } return objValue; } /* * (non-Javadoc) */ public void putCache(Object key, Object value ,Long lifeTime) { if(!isEnabled()){ return; } Long st = System.currentTimeMillis(); lifeTime = (null == lifeTime ? defaultLifeTime : lifeTime); CacheElement cacheObj = new CacheElement(); cacheObj.setCreateTime(System.currentTimeMillis()); cacheObj.setLifeTime(lifeTime); cacheObj.setValue(value); cacheObj.setKey(key); cacheMap.put(key, cacheObj); long et = System.currentTimeMillis(); if((et - st)>timeout){ if(this.logger.isWarnEnabled()){ this.logger.warn("putCache_timeout_" + (et - st) + "_[" + key + "]"); } } if(logger.isDebugEnabled()){ String message = ("putCache( " + cacheObj + " ) , 耗時(shí) " + (et - st) + "(毫秒)."); logger.debug(message); } if(lifeTime > defaultLifeTime && this.isWarnLongerLifeTime()){ if(logger.isWarnEnabled()){ String message = ("LifeTime[" + (lifeTime/1000) + "秒] too long for putCache(" + cacheObj + ")"); logger.warn(message); } } } /** * key 是否過(guò)期 * @param key * @return */ protected boolean isExpiredKey(Object key) { CacheElement cacheObj = cacheMap.get(key); return this.isExpiredCache(cacheObj); } /** * cacheObj 是否過(guò)期 * @param key * @return */ protected boolean isExpiredCache(CacheElement cacheObj) { if (cacheObj == null) { return false; } return cacheObj.isExpired(); } /* * (non-Javadoc) */ public void invalidateCaches(){ try{ cacheMap.clear(); }catch(Exception e){ e.printStackTrace(); } } /* * (non-Javadoc) */ public void invalidateCache(Object key){ try{ cacheMap.remove(key); }catch(Exception e){ e.printStackTrace(); } } /* * (non-Javadoc) */ public boolean containsKey(Object key) { return cacheMap.containsKey(key); } /* * (non-Javadoc) */ public int getSize() { return cacheMap.size(); } /* * (non-Javadoc) */ public Iterator<Object> getKeyIterator() { return cacheMap.keySet().iterator(); } /* * (non-Javadoc) */ public boolean isEnabled() { return this.enabled; } /* * (non-Javadoc) */ public void setEnabled(boolean enabled) { this.enabled = enabled; if(!this.enabled){ //清理緩存 this.invalidateCaches(); } } /** * 清理過(guò)期緩存 */ protected synchronized boolean gc(){ if(!isEnableGC()){ return false; } try{ iterateRemoveExpiredCache(); }catch(Exception e){ logger.error("gc() has error: " + e.getMessage(), e); } return true; } /** * 迭代模式 - 移除過(guò)期的 key * @param exceptKey */ private void iterateRemoveExpiredCache(){ long startTime = System.currentTimeMillis(); int size = cacheMap.size(); if(size ==0){ return; } int keyCount = 0; int removedCount = 0 ; int startIndex = 0; int endIndex = 0; try{ Object [] keys = cacheMap.keySet().toArray(); keyCount = keys.length; int maxIndex = keyCount -1 ; //初始化掃描下標(biāo) if(iterateScanAll){ startIndex = 0; endIndex = maxIndex; }else { int gcThreshold = this.getGcThreshold(); int iterateLen = gcThreshold > this.maxIterateSize ? this.maxIterateSize : gcThreshold; startIndex = this.iterateLastIndex; startIndex = ( (startIndex < 0 || startIndex > maxIndex) ? 0 : startIndex ); endIndex = (startIndex + iterateLen); endIndex = (endIndex > maxIndex ? maxIndex : endIndex); } //迭代清理 boolean flag = false; for(int i=startIndex; i<= endIndex; i++){ flag = this.removeExpiredKey(keys[i]); if(flag){ removedCount++; } } this.iterateLastIndex = endIndex; keys = null; }catch(Exception e){ logger.error("iterateRemoveExpiredCache -- 移除過(guò)期的 key時(shí)出現(xiàn)異常: " + e.getMessage(), e); } long endTime = System.currentTimeMillis(); StringBuffer sb = new StringBuffer(); sb.append("iterateRemoveExpiredCache [ size: ").append(size).append(", keyCount: ").append(keyCount) .append(", startIndex: ").append(startIndex).append(", endIndex: ").append(iterateLastIndex) .append(", removedCount: ").append(removedCount).append(", currentSize: ").append(this.cacheMap.size()) .append(", timeConsuming: ").append(endTime - startTime).append(", nowTime: ").append(new Date()) .append(" ]"); this.lastGCInfo = sb.toString(); if(logger.isInfoEnabled()){ logger.info("iterateRemoveExpiredCache -- 清理結(jié)果 -- "+ lastGCInfo); } } /** * 隨機(jī)模式 - 移除過(guò)期的 key */ private void randomRemoveExpiredCache(){ long startTime = System.currentTimeMillis(); int size = cacheMap.size(); if(size ==0){ return; } int removedCount = 0 ; try{ Object [] keys = cacheMap.keySet().toArray(); int keyCount = keys.length; boolean removeFlag = false; int removeRandomTimes = this.getGcThreshold(); removeRandomTimes = ( removeRandomTimes > this.getMaxRandomTimes() ? this.getMaxRandomTimes() : removeRandomTimes ); while(removeRandomTimes-- > 0){ int index = random.nextInt(keyCount); boolean flag = this.removeExpiredKey(keys[index]); if(flag){ removeFlag = true; removedCount ++; } } //嘗試 移除 首尾元素 if(!removeFlag){ this.removeExpiredKey(keys[0]); this.removeExpiredKey(keys[keyCount-1]); } keys=null; }catch(Exception e){ logger.error("randomRemoveExpiredCache -- 移除過(guò)期的 key時(shí)出現(xiàn)異常: " + e.getMessage(), e); } long endTime = System.currentTimeMillis(); StringBuffer sb = new StringBuffer(); sb.append("randomRemoveExpiredCache [ size: ").append(size).append(", removedCount: ").append(removedCount) .append(", currentSize: ").append(this.cacheMap.size()).append(", timeConsuming: ").append(endTime - startTime) .append(", nowTime: ").append(new Date()) .append(" ]"); this.lastGCInfo = sb.toString(); if(logger.isInfoEnabled()){ logger.info("randomRemoveExpiredCache -- 清理結(jié)果 -- "+ lastGCInfo); } } private boolean removeExpiredKey(Object key){ boolean flag = false; CacheElement cacheObj = null; if(null != key){ try{ cacheObj = cacheMap.get(key); boolean isExpiredCache = this.isExpiredCache(cacheObj); if(isExpiredCache){ cacheMap.remove(key); flag = true; } }catch(Exception e){ logger.error("removeExpired(" + key + ") -- error: " + e.getMessage(), e); } } if(!flag && logGCDetail){ this.logger.warn("removeExpiredKey(" + key + ") return [" + flag + "]--" + cacheObj); } return flag; } public int getInitialCapacity() { return initialCapacity; } public int getMaxCapacity() { return maxCapacity; } public int getGcMode() { return gcMode; } public void setGcMode(int gcMode) { this.gcMode = gcMode; } public int getGcIntervalTime() { return gcIntervalTime; } public void setGcIntervalTime(int gcIntervalTime) { this.gcIntervalTime = gcIntervalTime; } public boolean isEnableGC() { return enableGC; } public void setEnableGC(boolean enableGC) { this.enableGC = enableGC; } public boolean isIterateScanAll() { return iterateScanAll; } public void setIterateScanAll(boolean iterateScanAll) { this.iterateScanAll = iterateScanAll; } public float getGcFactor() { return gcFactor; } public void setGcFactor(float gcFactor) { this.gcFactor = gcFactor; } /** * gc 閥值 * @return */ public int getGcThreshold() { int threshold = ( int )( this .cacheMap.getMaxCapacity() * gcFactor ); return threshold; } public String getLastGCInfo() { return lastGCInfo; } public void setLastGCInfo(String lastGCInfo) { this .lastGCInfo = lastGCInfo; } public boolean isLogGCDetail() { return logGCDetail; } public void setLogGCDetail( boolean logGCDetail) { this .logGCDetail = logGCDetail; } public int getTimeout() { return timeout; } public void setTimeout( int timeout) { this .timeout = timeout; } public int getMaxIterateSize() { return maxIterateSize; } public void setMaxIterateSize( int maxIterateSize) { this .maxIterateSize = maxIterateSize; } public int getMaxRandomTimes() { return maxRandomTimes; } public void setMaxRandomTimes( int maxRandomTimes) { this .maxRandomTimes = maxRandomTimes; } public boolean isInitFlag() { return initFlag; } public long getDefaultLifeTime() { return defaultLifeTime; } public boolean isWarnLongerLifeTime() { return warnLongerLifeTime; } public void setWarnLongerLifeTime( boolean warnLongerLifeTime) { this .warnLongerLifeTime = warnLongerLifeTime; } //======================== dynMaxCapacity ======================== private int dynMaxCapacity = maxCapacity; public int getDynMaxCapacity() { return dynMaxCapacity; } public void setDynMaxCapacity( int dynMaxCapacity) { this .dynMaxCapacity = dynMaxCapacity; } public void resetMaxCapacity(){ if (dynMaxCapacity > initialCapacity && dynMaxCapacity != maxCapacity){ if (logger.isInfoEnabled()){ logger.info( "resetMaxCapacity( " + dynMaxCapacity + " ) start..." ); } synchronized (cacheMap){ LRULinkedHashMap<Object, CacheElement> cacheMap0 = new LRULinkedHashMap<Object, CacheElement>(initialCapacity ,dynMaxCapacity); cacheMap.clear(); cacheMap = cacheMap0; this .maxCapacity = dynMaxCapacity; } if (logger.isInfoEnabled()){ logger.info( "resetMaxCapacity( " + dynMaxCapacity + " ) OK." ); } } else { if (logger.isWarnEnabled()){ logger.warn( "resetMaxCapacity( " + dynMaxCapacity + " ) NO." ); } } } //======================== showCacheElement ======================== private String showCacheKey; public String getShowCacheKey() { return showCacheKey; } public void setShowCacheKey(String showCacheKey) { this .showCacheKey = showCacheKey; } public Object showCacheElement(){ Object v = null ; if ( null != this .showCacheKey){ v = cacheMap.get(showCacheKey); } return v; } } |
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://blog.csdn.net/u011683530/article/details/51029734