Guava Cache缓存的移除与读取

2017/05/23 16:53
阅读数 2.2W

 

1、通过put或putAll手动向Cache中添加数据,guava不缓存value是null的key。我们可以在系统启动的时候,就将某些数据手动放入缓存中,这样就可以避免系统启动后,第一个用户访问缓存不能命中的情况。

public static void testPut() {  
    Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(3).recordStats().build();  
  
    // 通过put或者putAll手动将数据添加到缓存  
    cache.put("id", "10");  
  
    Map<String, String> batch = new HashMap<>();  
    cache.put("name", "aty");  
    cache.put("addr", "sz");  
    cache.putAll(batch);  
  
    // 数量超出最大限制,会导致guava清除之前的数据,evictionCount增加1  
    // 手动添加缓存数据,不会影响其他缓存统计指标值  
    cache.put("new", "replace");  
    System.out.println(cache.stats());  
  
    // 不接受null  
    try {  
        cache.put("a", null);  
  
    } catch (NullPointerException e) {  
  
    }  
}  

2、通过getIfPresent/getAllPresent/get读取缓存中的数据。

public static void testGet() throws Exception {  
    Cache<String, String> cache = CacheBuilder.newBuilder().recordStats().build();  
    cache.put("name", "aty");  
    // 缓存未命中missCount加1  
    System.out.println(cache.getIfPresent("s") == null);  
    System.out.println(cache.stats());  
  
    // 缓存命中hitCount加1  
    System.out.println(cache.getIfPresent("name") != null);  
    System.out.println(cache.stats());  
  
  
    // Callable.call()不能返回null,否则guava报异常  
    Callable<String> callable = new Callable<String>() {  
        @Override  
        public String call() throws Exception {  
            Thread.sleep(2000);  
            return "demo";  
        }  
    };  
  
    // 使用guava Stopwatch计时  
    Stopwatch watch = Stopwatch.createStarted();  
    cache.get("a", callable);  
    watch.stop();  
  
    // 缓存不存在missCount加1,调用时间也会增加到totalLoadTime  
    System.out.println(cache.stats());  
  
    // 大致2s 可以证明: guava cache是在调用者的线程中执行callable任务的  
    System.out.println("elapse time=" + watch.elapsed(TimeUnit.MILLISECONDS));  
}  


3、如果明确知道某些缓存无用,我们可以通过invalidate/invalidateAll删除

public static void testDelete() {  
    Cache<String, String> cache = CacheBuilder.newBuilder().recordStats().build();  
    cache.put("a", "aty");  
    cache.put("b", "aty");  
    cache.put("c", "aty");  
    cache.put("d", "aty");  
  
  
    // 单个删除  
    cache.invalidate("a");  
    System.out.println(cache.stats());  
    System.out.println(cache.size()); // 3  
  
    // 批量删除  
    cache.invalidateAll(Arrays.asList("b", "c"));  
    System.out.println(cache.stats());  
    System.out.println(cache.size()); // 1  
  
    // 清除所有  
    cache.invalidateAll();  
    System.out.println(cache.stats());  
    System.out.println(cache.size()); // 0  
}  

4、通过调用cleanUp执行缓存清理操作,比如删除过期的key。

public static void testCleanup() throws Exception {  
    Cache<String, String> cache = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.SECONDS).build();  
    cache.put("a", "a");  
  
    // 睡眠2s让缓存过期  
    Thread.sleep(2000);  
  
    System.out.println(cache.size()); // 缓存大小仍然是1,因为调用这个方法不会触发缓存清除  
    System.out.println(cache.getIfPresent("a") == null);// 调用get/put会触发缓存清除  
  
  
    Cache<String, String> cache2 = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.SECONDS).build();  
    cache2.put("a", "a");  
  
    // 睡眠2s让缓存过期  
    Thread.sleep(2000);  
    cache2.cleanUp();// 手动触发缓存清除动作  
    System.out.println(cache2.size()); // 0  
}  


5、通过asMap可以拿到Cache底层使用的数据接口,通过这个map也可以添加或删除cache中的数据。通过map获取数据,不会影响缓存统计;通过map添加数据,可能会影响evictionCount。虽然可以对这个map进行迭代,不过有可能会出现获取到值是null的情况。

public static void testAsMap() throws Exception {  
    Cache<String, String> cache = CacheBuilder.newBuilder().build();  
    cache.put("a", "a");  
    cache.put("b", "b");  
    cache.put("c", "c");  
  
    // 通过底层map得到iterator,以便后面遍历  
    Iterator<String> iterator = cache.asMap().keySet().iterator();  
  
    // 1.启动一个线程进入睡眠状态  
    Thread thread = new Thread(new Runnable() {  
        @Override  
        public void run() {  
            try {  
                Thread.sleep(60 * 60 * 1000);  
            } catch (InterruptedException e) {  
                cache.invalidate("b");  
            }  
        }  
    });  
    thread.start();  
  
  
    while (iterator.hasNext()) {  
        String key = iterator.next();  
        if (key.equals("b")) {  
            thread.interrupt(); // 唤醒睡眠的线程,模拟线程的交替执行  
            Thread.sleep(100); // 让唤醒的线程执行完(清除缓存数据)  
        }  
  
        System.out.println("key=" + key + ",value=" + cache.getIfPresent(key));  
    }  
  
} 

 

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部