guava cache


 

緩存是提高性能的一把利器。
常用到的緩存技術有分布式緩存,像Redis、MC;也有本地緩存,像ehcache、guava cache等。這里說的是本地緩存guava cache。

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)

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM