guava cache

 

緩存是提升性能的一把利器。
經常使用到的緩存技術有分佈式緩存,像Redis、MC;也有本地緩存,像ehcache、guava cache等。這裏說的是本地緩存guava cache。java

guava cache剛開始接觸,這就記錄下來。。算法

    public static void main(String[] args) throws ExecutionException, InterruptedException{
        //緩存接口這裏是LoadingCache,LoadingCache在緩存項不存在時能夠自動加載緩存
        LoadingCache<Integer,Student> studentCache
                //CacheBuilder的構造函數是私有的,只能經過其靜態方法newBuilder()來得到CacheBuilder的實例
                = CacheBuilder.newBuilder()
                //設置併發級別爲8,併發級別是指能夠同時寫緩存的線程數
                .concurrencyLevel(8)
                //設置寫緩存後8秒鐘過時
                .expireAfterWrite(8, TimeUnit.SECONDS)
          //設置寫緩存後1秒鐘刷新
         .refreshAfterWrite(1, TimeUnit. SECONDS)                
//設置緩存容器的初始容量爲10                 .initialCapacity(10)                 //設置緩存最大容量爲100,超過100以後就會按照LRU最近雖少使用算法來移除緩存項                 .maximumSize(100)                 //設置要統計緩存的命中率                 .recordStats()                 //設置緩存的移除通知                 .removalListener(new RemovalListener<Object, Object>() {                     @Override                     public void onRemoval(RemovalNotification<Object, Object> notification) {                         System.out.println(notification.getKey() + " was removed, cause is " + notification.getCause());                     }                 })                 //build方法中能夠指定CacheLoader,在緩存不存在時經過CacheLoader的實現自動加載緩存                 .build(                         new CacheLoader<Integer, Student>() {                             @Override                             public Student load(Integer key) throws Exception {                                 System.out.println("load student " + key);                                 Student student = new Student();                                 student.setId(key);                                 student.setName("name " + key);                                 return student;                             }                         }                 );         for (int i=0;i<20;i++) {             //從緩存中獲得數據,因爲咱們沒有設置過緩存,因此須要經過CacheLoader加載緩存數據             Student student = studentCache.get(1);             System.out.println(student);             //休眠1秒             TimeUnit.SECONDS.sleep(1);         }         System.out.println("cache stats:");         //最後打印緩存的命中率等 狀況         System.out.println(studentCache.stats().toString());     }

還有另外一種方法緩存

package com;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import com.google.common.cache.*;

/** 
 * @author  做者 PZhang  E-mail:pzhang@rxhui.com 
 * @date 建立時間:2017-2-15 上午9:58:00 
 * @version 1.0 
 * @parameter   
 * @return  
 */
public class CacheModel {
    public Student getStudent(Integer key){
        System.out.println("load student " + key);
        Student student = new Student();
        student.setId(key);
        student.setName("name " + key);
        return student;
    }
    //load Method
    public void loadCacheA() throws Exception{
         LoadingCache<Integer,Student> studentCache= CacheBuilder.newBuilder().concurrencyLevel(8).
                 expireAfterWrite(8, TimeUnit.SECONDS).refreshAfterWrite(1, TimeUnit. SECONDS).initialCapacity(10).maximumSize(100)
                 .recordStats().removalListener(new RemovalListener<Object, Object>() {
                     public void onRemoval(RemovalNotification<Object, Object> notification) {
                                 System.out.println(notification.getKey() + " was removed, cause is " + notification);}
                     }).build(
                    new CacheLoader<Integer, Student>() {
                        @Override
                        public Student load(Integer key) throws Exception {
                            return getStudent(key);
                           }
                        }
          );

         for (int i=0;i<20;i++) {
           Student student = studentCache.get(1);
           System.out.println(student);
           TimeUnit.SECONDS.sleep(1);
         }

         System.out.println("cache stats:");
         System.out.println(studentCache.stats().toString());
         
    }
    //call back Method
    public void loadCacheB(final Integer key) throws Exception{
         Cache<Integer, Student> cache = CacheBuilder.newBuilder().maximumSize(1000).recordStats().expireAfterWrite(8, TimeUnit.SECONDS).build();  
             
         for (int i=0;i<20;i++) {
                System.out.println(cache.get(key, new Callable<Student>() {  
                     public Student call() {  
                        return getStudent(key);
                    }  
                }));
                TimeUnit.SECONDS.sleep(1);
              }

              System.out.println("cache stats:");
              System.out.println(cache.stats().toString());
    }
    
    public static void main(String[] args) throws Exception {
        CacheModel cache = new CacheModel();
        cache.loadCacheB(2);
    }
    
    
    
}

 

 

  guava Cache數據移除:併發

  guava作cache時候數據的移除方式,在guava中數據的移除分爲被動移除和主動移除兩種。
  被動移除數據的方式,guava默認提供了三種方式:
  1.基於大小的移除:看字面意思就知道就是按照緩存的大小來移除,若是即將到達指定的大小,那就會把不經常使用的鍵值對從cache中移除。
  定義的方式通常爲 CacheBuilder.maximumSize(long),還有一種一種能夠算權重的方法,我的認爲實際使用中不太用到。就這個經常使用的來看有幾個注意點,
    其一,這個size指的是cache中的條目數,不是內存大小或是其餘;
    其二,並非徹底到了指定的size系統纔開始移除不經常使用的數據的,而是接近這個size的時候系統就會開始作移除的動做;
    其三,若是一個鍵值對已經從緩存中被移除了,你再次請求訪問的時候,若是cachebuild是使用cacheloader方式的,那依然仍是會從cacheloader中再取一次值,若是這樣尚未,就會拋出異常
  2.基於時間的移除:guava提供了兩個基於時間移除的方法
    expireAfterAccess(long, TimeUnit)  這個方法是根據某個鍵值對最後一次訪問以後多少時間後移除
    expireAfterWrite(long, TimeUnit)  這個方法是根據某個鍵值對被建立或值被替換後多少時間移除
  3.基於引用的移除:
  這種移除方式主要是基於java的垃圾回收機制,根據鍵或者值的引用關係決定移除
  主動移除數據方式,主動移除有三種方法:
  1.單獨移除用 Cache.invalidate(key)
  2.批量移除用 Cache.invalidateAll(keys)
  3.移除全部用 Cache.invalidateAll()
  若是須要在移除數據的時候有所動做還能夠定義Removal Listener,可是有點須要注意的是默認Removal Listener中的行爲是和移除動做同步執行的,若是須要改爲異步形式,能夠考慮使用RemovalListeners.asynchronous(RemovalListener, Executor)異步

相關文章
相關標籤/搜索