Mybatis源碼-Cache包的內容

今天看完mybatis所有緩存裝飾類,總結整理一下

1、BlockingCache

上篇已經說了,BlockingCache 它特點就是不同緩存key會阻塞,如果一個線程沒有獲取某個key對應value,它就不會釋放鎖,它鎖採用是ReentrantLock(重入鎖),同一個線程可以加鎖多次,但是也必須解鎖相同的次數,其他線程纔可訪問該key,進行加鎖。

2、FifoCache(先進先出緩存裝飾類)

  1. 它的實現是通過LinkedList雙隊列方式存入緩存的key,一端放入最新緩存的key,如果超過閾值,就在另一端移除緩存key
  2. 默認大小隊列的大小是1024

3、LoggingCache(日誌緩存裝飾類)

  1. 設計主要目的是在debug模式調試某個緩存的命中率,也就是
  2. 命中率=獲取到值次數/請求次數

4、LruCache(最近最少使用緩存裝飾類)

  1. 設計思路就是用進廢退思想,經常用會放在前面不會被清除掉(通過put或get方法獲取某個緩存key對象,那麼這個緩存key自動排在最前面)
  2. 默認的大小也是1024
  3. 它是採用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. 第一它並沒有定時任務去清除緩存,只是調用這個方法纔會真正的清除
  2. 默認緩存清除時間是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(序列化緩存裝飾類)

  1. 本質就是把對象以byte[] 數組存入緩存對象中
  2. 緩存對象必須要實現serializable接口
  3. 自定義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(軟引用緩存裝飾類)

  1. 一般用於內存比較敏感,當內存不夠的時候,GC可以進清除這些緩存
  2. 裏面有兩個成員變量一個是避免GC回收集合(hardLinksToAvoidGarbageCollection),默認大小是256,一個關聯GC收集(queueOfGarbageCollectedEntries)之後,將回收對象存入到ReferenceQueue中來標記該對象已經被回收,緩存真正去移除這個緩存對象
  3. hardLinksToAvoidGarbageCollection集合進行操作的是採用同步操作

8、WeakCache(弱引用緩存裝飾類)

1.這個實現類似SoftCache,它比SoftCache更容易被GC回收

9、SynchronizedCache(同步緩存裝飾類)

  1. 這個主要是在方法上加了synchronized關鍵來實現同步操作

10、TransactionCache(事務緩存裝飾類)

  1. 這個是一個二級緩存事務的buffer
  2. put操作不會直接put到底層緩存對象中,而是put本對象中entriesToAddOnCommit
  3. 只有在commit操作之後纔會將entriesToAddOnCommit刷新到底層緩存對象中
  4. 這個類支持BlockingCache,但是好像有bug
  5. 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、總結

  1. 除了PerpetualCache是真正緩存對象,也就是底層緩存對象,以上10種都是裝飾類,豐富PerpetualCache功能,實現它的新特性。
  2. 裝飾類的主要操作對象是緩存key,通過緩存key實現一些功能
  3. PerpetualCache底層是HashMap進行存儲緩存
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章