常见java本地缓存

Caffeine

特点

Caffeine的底层数据存储采用ConcurrentHashMap。

Caffeine是Spring 5默认支持的Cache,可见Spring对它的看重,Spring抛弃Guava转向了Caffeine。

Caffeine可以看作是Guava Cache的增强版,采用了一种结合LRU、LFU优点的算法:W-TinyLFU,在性能上有明显的优越性

依赖

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.9.3</version>
</dependency>

 简单使用

    public static void main(String[] args) throws InterruptedException {
        Cache<Object, Object> cache = Caffeine.newBuilder()
                // 初始容量
                .initialCapacity(100)
                // 最大缓存数
                .maximumSize(1000)
                // 过期时间
                .expireAfterAccess(5, TimeUnit.SECONDS)
                // 失效时触发,不会自动触发
                .removalListener((k,v,removeCause)->{
                    System.out.println("--------------"+k);
                }).recordStats()
                .build();
        cache.put("a","b");
        System.out.println(cache.getIfPresent("a")); // b
        Thread.sleep(6000);
//        cache.invalidate("a");  // 触发removalListener
        System.out.println(cache.getIfPresent("a")); // null
        System.out.println(cache.get("a", k -> { // 不存在则填充值,之前的过期触发removalListener
            System.out.println("进入get");
            return k;
        }));
    }

Guava Cache

特点

Guava是Google团队开源的一款 Java 核心增强库,包含集合、并发原语、缓存、IO、反射等工具箱,性能和稳定性上都有保障,应用十分广泛。Guava Cache支持很多特性:

  • 支持最大容量限制
  • 支持两种过期删除策略(插入时间和访问时间)
  • 支持简单的统计功能
  • 基于LRU算法实现

依赖

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>18.0</version>
</dependency>

简单使用

    public static void main(String[] args) throws Exception {
        LoadingCache<String,String> loadingCache
                //CacheBuilder的构造函数是私有的,只能通过其静态方法newBuilder()来获得CacheBuilder的实例
                = CacheBuilder.newBuilder()
                //设置并发级别为8,并发级别是指可以同时写缓存的线程数
//                .concurrencyLevel(8)
                //设置写缓存后8秒钟过期
                .expireAfterWrite(2, TimeUnit.SECONDS)
//                .expireAfterAccess(10, TimeUnit.MINUTES)//设置时间对象没有被读/写访问则对象从内存中删除
                //设置缓存容器的初始容量为10
                .initialCapacity(10)
                //设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项
                .maximumSize(100)
                //设置要统计缓存的命中率
                .recordStats()
                //设置缓存的移除通知
                .removalListener((all)->{
                    System.out.println("移除key:"+all.getKey());
                })
                //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
                .build(
                        new CacheLoader<String, String>() {
                            @Override
                            public String load(String s) throws Exception {
                                return "b";
                            }
                        }
                );
        String a = loadingCache.get("a"); // 不存在key为“a”则触发load() return "b";
//        loadingCache.invalidate("a"); // 手动失效key,触发removalListener, System.out.println("移除key:"+all.getKey());
        TimeUnit.SECONDS.sleep(3);
        loadingCache.get("a"); // 过期触发removalListener, System.out.println("移除key:"+all.getKey());
    }

Ehcache

特点

其缓存的数据可以放在内存里面,也可以放在硬盘上。

ehcache的核心是cacheManager,cacheManager是用来管理cache(缓存)的。

一个应用下可以有多个cacheManager,而一个cacheManager下又可以有多个cache

cache内部保存的是一个的element,一个element中保存的是一个key和value的配对。

1、快速

2、简单

3、多种缓存策略

4、缓存数据有两级:内存和磁盘,因此无须担心容量问题

5、缓存数据会在虚拟机重启的过程中写入磁盘

6、可通过RMI、可插入APi等方式进行分布式缓存

7、具有缓存和缓存管理器的监听接口

8、支持多缓存管理器示例,以及一个实例的多个缓存区域

9、提供hibernate的缓存实现

同Caffeine和Guava Cache相比,Encache的功能更加丰富,扩展性更强

ehcache也有缓存共享方案,不过是通过RMI或者Jgroup多播方式进行广播缓存通知更新,缓存共享复杂,维护不方便;简单的共享可以,但涉及缓存恢复、大数据缓存,则不适合。

 依赖

<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.9.0</version>
</dependency>

简单使用

    public static void main(String[] args) {
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                .withCache("cache",
                        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(20))) 声明一个容量为20的堆内缓存
                .build(true);
//        cacheManager.init(); // true
//        Cache<Long, String> cache =
//                cacheManager.getCache("cache", Long.class, String.class);
//        cache.put();
//        cache.get()
        Cache<Long, String> myCache = cacheManager.createCache("myCache",
                CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10))
                        .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(20)))//设置过期 可自定义过期策略
        );

        myCache.put(1L, "one!");
        String value = myCache.get(1L);
        cacheManager.removeCache("cache");
        cacheManager.close();
    }

WeakHashMap

jdk自带,根据合适场景使用

WeakHashMap.Entry 继承了WeakReference

弱引用的生存期特别短。垃圾回收的时候,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。

ExpiringMap

特点

我使用的场景理由:过期自动触发移除事件

依赖

<dependency>
    <groupId>net.jodah</groupId>
    <artifactId>expiringmap</artifactId>
    <version>0.5.8</version>
</dependency>

简单使用

public static void main(String[] args) throws InterruptedException {
        ExpiringMap<String, String> map = ExpiringMap.builder()
                .expirationPolicy(ExpirationPolicy.CREATED)
                .expirationListener((k,v)->{
                    System.out.println(k);
                    System.out.println(v);
                })
                .maxSize(123)
                .expiration(2, TimeUnit.SECONDS)
                .build();

        // Expires after 30 seconds or as soon as a 124th element is added and this is the next one to expire based on the expiration policy
        map.put("connection", "1");
        TimeUnit.SECONDS.sleep(3);
    }
// 可以使用ExpiringMap.builder().variableExpiration().build();然后搭配map,put(k,v, ExpirationPolicy.ACCESSED, 5, TimeUnit.MINUTES)为单个元素设置过期时间,不推荐

猜你喜欢

转载自blog.csdn.net/wai_58934/article/details/126443855
今日推荐