1. Spring local cache   【Spring 本地缓存】

Spring provided cacheable annotation since 3.1. It's very super convinient to use and can obviously boost application performance.

从3.1版本开始,Spring提供了cacheable注解。它使用起来非常方便,还可以很明显的提升应用性能。具体的,怎么使用呢?

First, create a cache bean.

首先,创建缓存bean。这里,我们设置一个三秒的本地缓存(写后3秒过期)。

@Beanpublic Cache ephemeralCache() {    return new ConcurrentMapCache(EPHEMERAL_CACHE, CacheBuilder.newBuilder()            .expireAfterWrite(3, TimeUnit.SECONDS)            .build().asMap(), false);}

Second, add @Cacheable to the existed method.

接下来,给想要使用缓存的已有方法加上@Cacheable注解

@Cacheable(cacheNames = AppCacheConfig.EPHEMERAL_CACHE, key = "{#root.methodName, 'test'}")public Integer genId() {    int i = ai.incrementAndGet();    System.out.println(String.format("populate cache %s", LocalDateTime.now()));    return i;}

Finally, enjoy!

然后,尽情体验缓存带来的快乐!

ExecutorService exe = Executors.newWorkStealingPool();exe.submit(() -> {    while (true) {        cacheApi.genId();        Thread.sleep(50);    }});

See output of below codes

下面的日志和最初的缓存设定完全吻合

2017-06-08 10:17:49.990  INFO 12460 --- [           main] com.loops.nbs.Application                : Started Application in 7.42 seconds (JVM running for 7.973)
populate cache 2017-06-08T10:17:52.372
populate cache 2017-06-08T10:17:55.379
populate cache 2017-06-08T10:17:58.387
populate cache 2017-06-08T10:18:01.394
populate cache 2017-06-08T10:18:04.402
populate cache 2017-06-08T10:18:07.409
populate cache 2017-06-08T10:18:10.417
populate cache 2017-06-08T10:18:13.426

2. Guava cache  【Guava 本地缓存】

Guava is a set of libraries provided by Google. In memory cache is part of it.

Guava是Google提供的一套工具库。这里只讨论其中的缓存部分。

public class GuavaCacheExample {
    static Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
            .expireAfterWrite(2, TimeUnit.SECONDS)
            .recordStats()
            .build();

    static LoadingCache<Integer, Integer> loadingCache = CacheBuilder.newBuilder()
            .expireAfterWrite(2, TimeUnit.SECONDS)
            .build(new CacheLoader<Integer, Integer>() {
                @Override
                public Integer load(Integer key) throws Exception {
                    System.out.println("populate cache");
                    return key * 10;
                }
            });

    static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public static void main(String[] args) throws Exception {
        useNormalCache();
    }

    static void useNormalCache() throws Exception {
        scheduler.scheduleWithFixedDelay(() -> System.out.println(cache.stats()), 0, 1, TimeUnit.SECONDS);
        for (int i = 0; i < 10; i++) {
            System.out.println(cache.get(0, () -> {
                Thread.sleep(500);
                return 10;
            }));
            Thread.sleep(300);
        }
    }

    static void useLoadingCache() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(loadingCache.get(1));
            Thread.sleep(300);
        }
    }
}

Usually, there are 2 types of caches

1) Cache

Cache is basic usage, it provides method to get and put cache.

Cache是基础用法,提供了get和put的操作。

2) LoadingCache

Loading cache requires a CacheLoader when cache is created. Every time when cache is expired or nonexisted, the load method will be called automatically and generate cache.

So user doesn't have to manually put cache back after cache is expired.

Loading cache在创建的时候需要给定 CacheLoader。如果缓存过期或者不存在,CacheLoader 的 load 方法就会被调用到并产生缓存。这样,用户就不用去关心那些过期的缓存项了。

Besides, we can add recordStats() when creating a cache object. Later we can monitor the cache usage by calling cache.stats()

Cache is created twice during the test, correspondingly, totalLoadTime (mesured in nano seconds) changed twice.

除此,我们还可以在创建缓存时使用 recordStats 来记录缓存的使用情况。之后用 cache 的 stats() 方法来观察。

测试过程中,我们的缓存产生了2次,totalLoadTime (纳秒为单位)也很好的佐证了这一点。

CacheStats{hitCount=0, missCount=0, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=0}
10
10
CacheStats{hitCount=1, missCount=1, loadSuccessCount=1, loadExceptionCount=0, totalLoadTime=502324777, evictionCount=0}
10
10
10
CacheStats{hitCount=4, missCount=1, loadSuccessCount=1, loadExceptionCount=0, totalLoadTime=502324777, evictionCount=0}
10
10
CacheStats{hitCount=6, missCount=1, loadSuccessCount=1, loadExceptionCount=0, totalLoadTime=502324777, evictionCount=1}
10
10
10
CacheStats{hitCount=8, missCount=2, loadSuccessCount=2, loadExceptionCount=0, totalLoadTime=1002802169, evictionCount=1}

3. Caffeine cache  【Caffeine 本地缓存】

Caffeine cache is an optimized cache for Java 8. It has similar apis to guava but provide higher performance, which makes it easy to migrate from Gauva to Caffeine.

See this report for more details https://github.com/ben-manes/caffeine/wiki/Benchmarks

咖啡因缓存是专为Java 8而生的。使用上和Guava很像(很容易迁移),但它在多线程情况下性能更高。上面有一个跑分链接,比较了各种本地缓存的性能。

public class CaffeineCacheExample {
    static Cache<Integer, Integer> cache = Caffeine.newBuilder()
            .expireAfterWrite(2, TimeUnit.SECONDS)
            .recordStats()
            .build();

    static LoadingCache<Integer, Integer> loadingCache = Caffeine.newBuilder()
            .expireAfterWrite(2, TimeUnit.SECONDS)
            .build(new CacheLoader<Integer, Integer>() {
                @Override
                public Integer load(Integer key) throws Exception {
                    System.out.println("populate cache");
                    return key * 10;
                }
            });

    static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public static void main(String[] args) throws Exception {
        useNormalCache();
    }

    static void useNormalCache() throws Exception {
        scheduler.scheduleWithFixedDelay(() -> System.out.println(cache.stats()), 0, 1, TimeUnit.SECONDS);
        for (int i = 0; i < 10; i++) {
            System.out.println(cache.get(0, k -> {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException ex) {
                    //ignore
                }
                return 10;
            }));
            Thread.sleep(300);
        }
    }

    static void useLoadingCache() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(loadingCache.get(1));
            Thread.sleep(300);
        }
    }
}

There exists slight difference between Guava and Caffeine

使用上,有一点小小的区别

1) Builder: Guava use CacheBuilder to create new builder while Caffeine use Caffeine.

创建Builder时,Guava使用CacheBuilder,咖啡因使用Caffeine

2) Get method: Guava pass callable for get method

两者的Get方法第二个参数略有区别Guava 传入Callable, 内部可以抛出异常,无需写冗余的try catch,而咖啡因传入Function,必须手动捕获可能的异常

V get(K var1, Callable<? extends V> var2) throws ExecutionException;

Caffeine pass Function for get method

 @CheckForNull
    V get(@Nonnull K var1, @Nonnull Function<? super K, ? extends V> var2);

Callable itself throws exception so we don't have to try catch the exception in the block while Function tolerates no exception.

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}
@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);

A comparison of local caches (1) 【本地缓存之比较 (1)】的更多相关文章

  1. A comparison of local caches (2) 【本地缓存之比较 (2)】

    接上一篇: A comparison of local caches (1) [本地缓存之比较 (1)] This article will compare the asynchronous loca ...

  2. 八、React实战:可交互待办事务表(表单使用、数据的本地缓存local srtorage、生命同期函数(页面加载就会执行函数名固定为componentDidMount()))

    一.项目功能概述 示例网址:http://www.todolist.cn/ 功能: 输入待做事项,回车,把任务添加到 [正在进行] [正在进行] 任务,勾选之后,变成已[经完成事项] [已完成事务], ...

  3. spring boot: 用redis的消息订阅功能更新应用内的caffeine本地缓存(spring boot 2.3.2)

    一,为什么要更新caffeine缓存? 1,caffeine缓存的优点和缺点 生产环境中,caffeine缓存是我们在应用中使用的本地缓存, 它的优势在于存在于应用内,访问速度最快,通常都不到1ms就 ...

  4. spring boot:使用spring cache+caffeine做进程内缓存(本地缓存)(spring boot 2.3.1)

    一,为什么要使用caffeine做本地缓存? 1,spring boot默认集成的进程内缓存在1.x时代是guava cache 在2.x时代更新成了caffeine, 功能上差别不大,但后者在性能上 ...

  5. Java8简单的本地缓存实现

    原文出处:lukaseder         Java8简单的本地缓存实现 这里我将会给大家演示用ConcurrentHashMap类和lambda表达式实现一个本地缓存.因为Map有一个新的方法,在 ...

  6. iOS五种本地缓存数据方式

    iOS五种本地缓存数据方式   iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...

  7. ImageLoader(多线程网络图片加载)+本地缓存 for windowsphone 7

    搞了好长一阵子wp,做点好事. C/S手机app中应用最多的是  获取网络图片,缓存到本地,展示图片 本次主要对其中的delay:LowProfileImageLoader进行修改,在获取图片的时候, ...

  8. lua模块demo(redis,http,mysql,cjson,本地缓存)

    1. lua模块demo(redis,http,mysql,cjson,本地缓存) 1.1. 配置 在nginx.conf中设置lua_shared_dict my_cache 128m; 开启ngi ...

  9. ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪

    ASP.NET MVC深入浅出(被替换)   一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...

随机推荐

  1. [JavaWeb]SpringSecurity-OAuth2.0 统一认证、资源分离的配置,用于分布式架构、模块化开发的认证体系

    前言 关于 OAuth2.0的认证体系,翻阅了好多资料,RCF 文档太多,看了一半就看不下去了,毕竟全英文的文档看起来,是有一点让我烦躁,但也对 OAuth2.0的认证流程有了一个基本的概念,之前用 ...

  2. 分布式文件系统 FastDFS 5.0.5 & Linux CentOS 7 安装配置(单点安装)——第一篇

    分布式文件系统 FastDFS 5.0.5 & Linux CentOS 7 安装配置(单点安装)--第一篇 简介 首先简单了解一下基础概念,FastDFS是一个开源的轻量级分布式文件系统,由 ...

  3. LeetCode 376. Wiggle Subsequence 摆动子序列

    原题 A sequence of numbers is called a wiggle sequence if the differences between successive numbers s ...

  4. Python资源汇总

    Python 目录: 管理面板 算法和设计模式 反垃圾邮件 资产管理 音频 验证 构建工具 缓存 ChatOps工具 CMS 代码分析和Linter 命令行工具 兼容性 计算机视觉 并发和并行性 组态 ...

  5. 开发一款直播APP系统软件应该有哪些功能,如何开发?

    1.技术实现层面: 技术相对都比较成熟,设备也都支持硬编码.IOS还提供现成的 Video ToolBox框架,可以对摄像头和流媒体数据结构进行处理,但Video ToolBox框架只兼容8.0以上版 ...

  6. 清北Day4

    版权声明:如需转载请标明出处,未得到本人许可请勿转载. 今天就可以看到传说中的 数据结构 嘿嘿嘿嘿 都有什么呢 链表 队列 栈 st表 hash 线段树 树链剖分 一.栈: 放出来这个看烂了的图 值得 ...

  7. stl map容器 学习

    #include<map> 1.map的声明: map<string,int>map_1; map_1 就是一个string对int的映射. 2.map的用法(映射): map ...

  8. Webgis开源解决方案之环境搭建(三)

    前两篇文章介绍了开源GIS服务器Geoserver的安装以及开源数据库Postgres的安装,这篇文章介绍开源前端udig软件的安装,使用在后续篇幅中介绍 开源前端目前主流的是QGIS或者udig,网 ...

  9. GitHub的实践

    GitHub的实践 2017-05-08,晴,来小米已经一周的时间了,感谢领导能给我一周的时间来熟悉 ubuntu.spring boot.maven.docker.github .大家会问,这些不都 ...

  10. OC比C中,新增的数据类型

    布尔型 BOOL 以及 boolean 1)这两者都是判断类型 2)在C底层这两者都是一个 char类型 占一个字符大小 3)BOOL 的取值为 YES / NO 其中NO =0 YES =1 4)b ...