Guava緩存器源碼分析——數據加載

     Guava緩存器加載數據的方式有兩種:同步(loadSync)與異步(loadAsync)。

     同步方式——
     只在取數據 V get(K, int, CacheLoader)執行過程中會被調用到。
     同步加載數據代碼如下:
          ListenableFuture<V> loadingFuture = loadingValueReference.loadFuture(key, loader);
          return getAndRecordStats(key, hash, loadingValueReference, loadingFuture);

     異步方式——
     只在刷新數據refresh(K, int, CacheLoader, boolean)執行過程中會被調用到。
     guava緩存器沒有提供類似refreshAll()的方法來刷新所有值,而只是提供了 refresh(Key)的方法來刷新某個鍵值對,這裏的刷新動作是異步執行的,如果有人在值被徹底刷新之前,取這個Key的值,返回的還是刷新前的值。

     在執行refresh時,會調用loadAsync方法來異步加載數據,同時通過isDone()方法來判斷任務是否完成,正常結束、異常或者是被取消,這個方法都會返回true。
      ListenableFuture<V> result = loadAsync(key, hash, loadingValueReference, loader);
           if (result.isDone()) {
             try {
               return Uninterruptibles.getUninterruptibly(result);
             } catch (Throwable t) {
        }
      }
      return null;

     不管是同步或異步方式,都會調用到loadFuture(key, loader)方法,先將數據取到。
     loadFuture執行流程:
     1、取key對應的舊值;
     2、舊值不存在,則調用load方法取新值。
     3、通過futureValue的set方法來設置新值,成功則返回futureValue,否則返回Futures.immediateFuture(newValue)。
     4、舊值存在,則調用reload方法重取新值。
     5、reload方法返回類型爲ListenableFuture<V>,結果不爲null則直接返回,否則返回 Futures.<V>immediateFuture(null)。
     Futures的immediateFuture方法,返回了一個ImmediateSuccessfulFuture對象,在其構造函數中初始化值,該Future不能被取消或超時,它的isDone()方法只返回true。
    

     異步方式,在取數完成後,將註冊一個監聽器,完成數據的最終加載並統計信息。
     loadingFuture.addListener(
          new Runnable() {
            @Override
            public void run() {
              try {
                    V newValue = getAndRecordStats(key, hash, loadingValueReference, loadingFuture);
                    loadingValueReference.set(newValue);
              } catch (Throwable t) {
                    logger.log(Level.WARNING, "Exception thrown during refresh", t);
                    loadingValueReference.setException(t);
              }
            }
          }, sameThreadExecutor);

     涉及的類:
這部分代碼,通過Runnable接口實現,沒有返回結果。   
其中SettableFuture通過set(Object)或setException(Throwable)來設置值。
       AbstractFuture類通過AbstractQueuedSynchronizer來處理同步問題和保證線程安全。所有涉及狀態改變的方法,都會返回一個boolean值來表明狀態改變是否成功,有效的狀態有running, completed, failed, cancelled。這個類通過ExecutionList來保證當Future結束時所有註冊的監聽器,或完成後添加的監聽器都能被執行。Runnable-Executor對存放在execution列表中,但不一定按它們添加的順序執行,如果一個監聽器在Future結束後添加,它將被立即執行,就算在它之前的監聽器還沒執行。
      如果需要知道返回結果,可以使用Guava提供的ListenableFutureTask類,該類繼承至FutureTask並實現了ListenableFuture接口, 可自由選擇實現Runnable的void run()方法,或Callable的 V call()方法(有返回結果),這幾個類看的不夠仔細,需要再研究。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章