Java-类库-Guava-cache

简介: 缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。 缓存在很多系统和架构中都用广泛的应用,例如:  1.CPU缓存   2.操作系统缓存   3.本地缓存   4.分布式缓存   5.HTTP缓存   6.数据库缓存   等等,可以说在计算机和网络领域,缓存无处不在。

缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。

 缓存在很多系统和架构中都用广泛的应用,例如:

  1.CPU缓存
  2.操作系统缓存
  3.本地缓存
  4.分布式缓存
  5.HTTP缓存
  6.数据库缓存
  等等,可以说在计算机和网络领域,缓存无处不在。可以这么说,只要有硬件性能不对等,涉及到网络传输的地方都会有缓存的身影。

  Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。整体上来说Guava cache 是本地缓存的不二之选,简单易用,性能好。
   Guava Cache有两种创建方式:

  1. cacheLoader
  2. callable callback
 通过这两种方法创建的cache,和通常用map来缓存的做法比,不同在于,这两种方法都实现了一种逻辑——从缓存中取key X的值,如果该值已经缓存过了,则返回缓存中的值,如果没有缓存过,可以通过某个方法来获取这个值。但不同的在于cacheloader的定义比较宽泛,是针对整个cache定义的,可以认为是统一的根据key值load value的方法。而callable的方式较为灵活,允许你在get的时候指定
 cacheLoader方式实现实例:
 

 @Test
    public void TestLoadingCache() throws Exception{
        LoadingCache<String,String> cahceBuilder=CacheBuilder
        .newBuilder()
        .build(new CacheLoader<String, String>(){
            @Override
            public String load(String key) throws Exception {        
                String strProValue="hello "+key+"!";                
                return strProValue;
            }

        });        

        System.out.println("jerry value:"+cahceBuilder.apply("jerry"));
        System.out.println("jerry value:"+cahceBuilder.get("jerry"));
        System.out.println("peida value:"+cahceBuilder.get("peida"));
        System.out.println("peida value:"+cahceBuilder.apply("peida"));
        System.out.println("lisa value:"+cahceBuilder.apply("lisa"));
        cahceBuilder.put("harry", "ssdded");
        System.out.println("harry value:"+cahceBuilder.get("harry"));
    }

callable callback的实现:

 @Test
    public void testcallableCache()throws Exception{
        Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build();  
        String resultVal = cache.get("jerry", new Callable<String>() {  
            public String call() {  
                String strProValue="hello "+"jerry"+"!";                
                return strProValue;
            }  
        });  
        System.out.println("jerry value : " + resultVal);

        resultVal = cache.get("peida", new Callable<String>() {  
            public String call() {  
                String strProValue="hello "+"peida"+"!";                
                return strProValue;
            }  
        });  
        System.out.println("peida value : " + resultVal);  
    }

  输出:
  jerry value : hello jerry!
  peida value : hello peida!

 cache的参数说明:

  回收的参数:
  1. 大小的设置:CacheBuilder.maximumSize(long) CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long)
  2. 时间:expireAfterAccess(long, TimeUnit) expireAfterWrite(long, TimeUnit)
  3. 引用:CacheBuilder.weakKeys() CacheBuilder.weakValues() CacheBuilder.softValues()
  4. 明确的删除:invalidate(key) invalidateAll(keys) invalidateAll()
  5. 删除监听器:CacheBuilder.removalListener(RemovalListener)
  

  refresh机制:
  1. LoadingCache.refresh(K) 在生成新的value的时候,旧的value依然会被使用。
  2. CacheLoader.reload(K, V) 生成新的value过程中允许使用旧的value
  3. CacheBuilder.refreshAfterWrite(long, TimeUnit) 自动刷新cache
 

 /**
     * 不需要延迟处理(泛型的方式封装)
     * @return
     */
    public  <K , V> LoadingCache<K , V> cached(CacheLoader<K , V> cacheLoader) {
          LoadingCache<K , V> cache = CacheBuilder
          .newBuilder()
          .maximumSize(2)
          .weakKeys()
          .softValues()
          .refreshAfterWrite(120, TimeUnit.SECONDS)
          .expireAfterWrite(10, TimeUnit.MINUTES)        
          .removalListener(new RemovalListener<K, V>(){
            @Override
            public void onRemoval(RemovalNotification<K, V> rn) {
                System.out.println(rn.getKey()+"被移除");  

            }})
          .build(cacheLoader);
          return cache;
    }

    /**
     * 通过key获取value
     * 调用方式 commonCache.get(key) ; return String
     * @param key
     * @return
     * @throws Exception
     */

    public  LoadingCache<String , String> commonCache(final String key) throws Exception{
        LoadingCache<String , String> commonCache= cached(new CacheLoader<String , String>(){
                @Override
                public String load(String key) throws Exception {
                    return "hello "+key+"!";    
                }
          });
        return commonCache;
    }

    @Test
    public void testCache() throws Exception{
        LoadingCache<String , String> commonCache=commonCache("peida");
        System.out.println("peida:"+commonCache.get("peida"));
        commonCache.apply("harry");
        System.out.println("harry:"+commonCache.get("harry"));
        commonCache.apply("lisa");
        System.out.println("lisa:"+commonCache.get("lisa"));
    }
peida:hello peida!
harry:hello harry!
peida被移除
lisa:hello lisa!

基于泛型的Callable Cache实现:

private static Cache<String, String> cacheFormCallable = null; 


    /**
     * 对需要延迟处理的可以采用这个机制;(泛型的方式封装)
     * @param <K>
     * @param <V>
     * @param key
     * @param callable
     * @return V
     * @throws Exception
     */
    public static <K,V> Cache<K , V> callableCached() throws Exception {
          Cache<K, V> cache = CacheBuilder
          .newBuilder()
          .maximumSize(10000)
          .expireAfterWrite(10, TimeUnit.MINUTES)
          .build();
          return cache;
    }


    private String getCallableCache(final String userName) {
           try {
             //Callable只有在缓存值不存在时,才会调用
             return cacheFormCallable.get(userName, new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println(userName+" from db");
                    return "hello "+userName+"!";
               }
              });
           } catch (ExecutionException e) {
              e.printStackTrace();
              return null;
            } 
    }

    @Test
    public void testCallableCache() throws Exception{
         final String u1name = "peida";
         final String u2name = "jerry"; 
         final String u3name = "lisa"; 
         cacheFormCallable=callableCached();
         System.out.println("peida:"+getCallableCache(u1name));
         System.out.println("jerry:"+getCallableCache(u2name));
         System.out.println("lisa:"+getCallableCache(u3name));
         System.out.println("peida:"+getCallableCache(u1name));

    }

  输出:


peida from db
peida:hello peida!
jerry from db
jerry:hello jerry!
lisa from db
lisa:hello lisa!
peida:hello peida!

  说明:Callable只有在缓存值不存在时,才会调用,比如第二次调用getCallableCache(u1name)直接返回缓存中的值

  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)

目录
相关文章
|
1月前
|
SQL Java Apache
Java类库
Java类库
14 0
|
6月前
|
Java 数据库连接
Java类库的使用
Java类库(Java Class Library)是一组预定义的类和接口,提供了丰富的功能和工具,可以帮助开发人员快速开发Java应用程序。Java类库是Java开发的核心部分,包含了各种常用的类和接口,用于处理字符串、日期、集合、输入输出、网络通信、图形界面等各种任务。 Java类库分为两部分:核心类库(Core Class Library)和扩展类库(Extension Class Library)。 核心类库包括了Java语言的基本类和接口,如Object、String、Math、ArrayList、HashMap等。这些类和接口提供了常用的功能和数据结构,可以直接在代码中使用。
71 0
|
3月前
|
缓存 安全 Java
JAVA 常用类库 StringBuffer 和 StringBuilder
● 当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。 ● 和 String 类不同的是,StringBuffer 和 StringBuilder类的对象能够被多次的修改,并且不产生新的未使用对象。 ● StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。 ● 由于 StringBuilder 相较于 StringBuffer 有速度优势,多数情况下建议使用 StringBuilder类。然而在应用程序要求线程安全的情况下,
|
4月前
|
安全 Java 关系型数据库
Java核心类库
Java核心类库
56 1
|
6月前
|
存储 算法 安全
Java常用类库与技巧
Java常用类库与技巧
40 0
|
8月前
|
算法 Java 调度
Java常用类库(System、Arrays、定时调度、Base64加密解密)
1.System类,2.Arrays数组操作类,3.定时调度,4.Base64加密与解密
55 0
|
8月前
|
安全 Java 数据库连接
Java常用类库中(ThreadLocal、Comparable比较器、AutoCloseable、Optional空处理)附带相关面试题
1.ThreadLocal线程独立,2.Comparable比较器与Comparetor,3.AutoCloseable接口,4.Optional空处理
45 0
|
8月前
|
存储 安全 Java
Java类库StrringBuffer类、Math、SimpleDateFormat、Random随机数、大数字处理类和UUID 无重复数据(附带面试题)
1.StrringBuffer类 CharConsequnse接口,2.Math数学计算,3.Date日期处理类与SimpleDateFormat、4.Random随机数、5.大数字处理类、6.UUID 无重复数据
75 0
|
11月前
|
SQL 编解码 缓存
贼好用的Java工具类库,GitHub星标10k+你在用吗?
Hutool是Hu + tool的自造词,前者致敬我的“前任公司”,后者为工具之意,谐音“糊涂”,寓意追求“万事都作糊涂观,无所谓失,无所谓得”的境界。 Hutool是一个Java工具包,也只是一个工具包,它帮助我们简化每一行代码,减少每一个方法,让Java语言也可以“甜甜的”。Hutool最初是我项目中“util”包的一个整理,后来慢慢积累并加入更多非业务相关功能,并广泛学习其它开源项目精髓,经过自己整理修改,最终形成丰富的开源工具集。(抄自作者简介)
|
11月前
|
存储 Java 程序员

热门文章

最新文章