今天看完mybatis所有緩存裝飾類,總結整理一下
文章目錄
1、BlockingCache
上篇已經說了,BlockingCache 它特點就是不同緩存key會阻塞,如果一個線程沒有獲取某個key對應value,它就不會釋放鎖,它鎖採用是ReentrantLock(重入鎖),同一個線程可以加鎖多次,但是也必須解鎖相同的次數,其他線程纔可訪問該key,進行加鎖。
2、FifoCache(先進先出緩存裝飾類)
- 它的實現是通過LinkedList雙隊列方式存入緩存的key,一端放入最新緩存的key,如果超過閾值,就在另一端移除緩存key
- 默認大小隊列的大小是1024
3、LoggingCache(日誌緩存裝飾類)
- 設計主要目的是在debug模式調試某個緩存的命中率,也就是
- 命中率=獲取到值次數/請求次數
4、LruCache(最近最少使用緩存裝飾類)
- 設計思路就是用進廢退思想,經常用會放在前面不會被清除掉(通過put或get方法獲取某個緩存key對象,那麼這個緩存key自動排在最前面)
- 默認的大小也是1024
- 它是採用LinkedHashMap實現的,重寫removeEldestEntry的方法,判斷當前緩存key的個數是否超過閾值,如果超過了,就獲取到最不經常用的key,在下一次put的時候,進行移除該key的緩存對象
測試代碼
/**
* 默認大小是1024, 會清除索引爲0數據
* 最新操作的元素總是放在最後位置, 從前面刪除元素
* @param args
*/
public static void main(String[] args) {
LruCache lruCache = new LruCache(new PerpetualCache("com.jack.pa"));
lruCache.setSize(3);
lruCache.putObject(1, 1);
lruCache.putObject(2, 2);
lruCache.putObject(3, 3); // 123
lruCache.putObject(4, 4); // 234
lruCache.getObject(3); // 243
for (Map.Entry<Object, Object> entry : lruCache.keyMap.entrySet()) {
System.out.println("key:"+ entry.getKey() + " value:" + entry.getValue());
}
}
5、ScheduledCache(定間隔清理緩存裝飾類)
- 第一它並沒有定時任務去清除緩存,只是調用這個方法纔會真正的清除
- 默認緩存清除時間是1小時
/**
* 立即獲取:1
延遲2秒獲取:null
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
ScheduledCache scheduledCache = new ScheduledCache(new PerpetualCache("com.jack.pa"));
scheduledCache.setClearInterval(1000);
scheduledCache.putObject(1,1);
System.out.println("立即獲取:" + scheduledCache.getObject(1));
Thread.sleep(2000);
System.out.println("延遲2秒獲取:" + scheduledCache.getObject(1));
}
6、SerializedCache(序列化緩存裝飾類)
- 本質就是把對象以byte[] 數組存入緩存對象中
- 緩存對象必須要實現serializable接口
- 自定義ObjectInputStream 重寫resolveClass方法, 使用自己Resource獲取Class類
/**
* 把緩存的對象採用byte[]數組進行存儲
* @param args
*/
public static void main(String[] args) {
LruCache serializedCache = new LruCache(new SerializedCache(new PerpetualCache("com.jack.pa")));
serializedCache.putObject("1121211","21132131312");
serializedCache.getObject("1121211");
}
7、SoftCache(軟引用緩存裝飾類)
- 一般用於內存比較敏感,當內存不夠的時候,GC可以進清除這些緩存
- 裏面有兩個成員變量一個是避免GC回收集合(hardLinksToAvoidGarbageCollection),默認大小是256,一個關聯GC收集(queueOfGarbageCollectedEntries)之後,將回收對象存入到ReferenceQueue中來標記該對象已經被回收,緩存真正去移除這個緩存對象
- hardLinksToAvoidGarbageCollection集合進行操作的是採用同步操作
8、WeakCache(弱引用緩存裝飾類)
1.這個實現類似SoftCache,它比SoftCache更容易被GC回收
9、SynchronizedCache(同步緩存裝飾類)
- 這個主要是在方法上加了synchronized關鍵來實現同步操作
10、TransactionCache(事務緩存裝飾類)
- 這個是一個二級緩存事務的buffer
- put操作不會直接put到底層緩存對象中,而是put本對象中entriesToAddOnCommit
- 只有在commit操作之後纔會將entriesToAddOnCommit刷新到底層緩存對象中
- 這個類支持BlockingCache,但是好像有bug
- entriesMissedInCache這個集合是存在沒有獲取到值的緩存key集合(Set集合)
/**
* 他說這個類支持BlockingCache,但是發現多次請求同一個key,導致多次加鎖,但是這個entriesMissedInCache是Set集合
* 導致多次加鎖之後還是存在一個對象,在解鎖的時候只能解鎖一次導致其他其他線程不能獲取緩存key,所以認爲這裏可能有bug,把Set緩存List不會出現
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
BlockingCache blockingCache = new BlockingCache(new PerpetualCache("com.jack.pa"));
TransactionalCache transactionalCache = new TransactionalCache(blockingCache);
for(int i=0 ; i < 10; i++) {
transactionalCache.getObject(1);
}
transactionalCache.rollback();
Thread tryLock = new Thread(()->{
transactionalCache.getObject(1);
});
tryLock.start();
tryLock.join();
}
11、總結
- 除了PerpetualCache是真正緩存對象,也就是底層緩存對象,以上10種都是裝飾類,豐富PerpetualCache功能,實現它的新特性。
- 裝飾類的主要操作對象是緩存key,通過緩存key實現一些功能
- PerpetualCache底層是HashMap進行存儲緩存