淘先锋技术网

首页 1 2 3 4 5 6 7

前言:

最近公司的服务调用系统,需要把放进Redis中的一部分数据,直接放进内存中进行取读。这样,可以加快取读速度并且还可以减配Redis集群的服务器配置。一开始,我打算有手写一个带过期的Map。但是,自我感觉技术菜鸟,手写可能想不周全,更容易出问题。所以我在网络上寻找一番,找到了ExpiringMap这个开源架包。简单看了一下ExpiringMap的文档,应该可以支持业务改造。下面,我介绍一下ExpiringMap的使用。

正文:

一、ExpiringMap简介:

它具有高性能、低开销、零依赖、线程安全、使用ConcurrentMa的实现过期entries等优点。主要特点包括:过期策略、可变有效期、最大尺寸、侦听器过期、延迟输入加载、过期自省。

二、项目地址:

https://github.com/jhalterman/expiringmap

三、使用:

0.引入架包依赖:

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

1.简单使用,设置5秒的过期时间:

    /**
     * 简单使用,设置5秒的过期时间
     * 
     * @throws InterruptedException
     */
    private static void test1() throws InterruptedException {
        ExpiringMap<String, String> map = ExpiringMap.builder()
                // 设置过期时间和过期时间单位
                .expiration(5, TimeUnit.SECONDS)
                .build();
        map.put("1", "测试");
        map.put("2", "测试");
        Thread.sleep(6000);
        System.out.println(map); // {}
    }

 2.过期策略的使用(CREATED、ACCESSED):

   /**
     * 过期策略的使用:
     * CREATED:  在每次更新元素时,过期倒计时清零
     * ACCESSED: 在每次访问元素时,过期倒计时清零
     *
     * @throws InterruptedException
     */
    private static void test2() throws InterruptedException {

        // 使用默认的CREATED策略:
        System.out.println("----使用默认的CREATED策略:----");
        ExpiringMap<String, String> map = ExpiringMap.builder()
                .expirationPolicy(ExpirationPolicy.CREATED)
                .expiration(2, TimeUnit.SECONDS)
                .build();
        // -- 测试CREATED策略,访问的情况
        map.put("1", "测试");
        Thread.sleep(1000);
        System.out.println(map.get("1"));  // 测试
        Thread.sleep(1001);
        System.out.println(map.get("1"));  // null
        // -- 测试CREATED策略,更新的情况
        map.put("2","测试");
        Thread.sleep(1000);
        System.out.println(map.get("2")); // 测试
        map.put("2","测试1");
        Thread.sleep(1000);
        System.out.println(map.get("2")); // 测试1
        Thread.sleep(900);
        System.out.println(map.get("2")); // 测试1
        Thread.sleep(200);
        System.out.println(map.get("2")); // null


        // 使用默认的ACCESSED策略:
        System.out.println("----使用默认的ACCESSED策略:----");
        ExpiringMap<String, String> map1 = ExpiringMap.builder()
                .expirationPolicy(ExpirationPolicy.ACCESSED)
                .expiration(2, TimeUnit.SECONDS)
                .build();
        // -- 测试ACCESSED策略,访问的情况
        map1.put("1", "测试");
        Thread.sleep(1000);
        System.out.println(map1.get("1"));  // 测试
        Thread.sleep(1100);
        System.out.println(map1.get("1"));  // 测试
        Thread.sleep(2100);
        System.out.println(map1.get("1"));  // null
        
        // 只是访问时,过期倒计时清零
        map1.put("2","测试");
        Thread.sleep(1000);
        System.out.println(map1); // {2=测试}
        Thread.sleep(1100);
        System.out.println(map1); // {}
    }

3.可变有效期,即单独为每个entity设置过期时间和策略:

    /**
     * 可变有效期,即单独为每个entity设置过期时间和策略:
     *
     * @throws InterruptedException
     */
    private static void test3() throws InterruptedException {
        ExpiringMap<String, String> map = ExpiringMap.builder()
                .variableExpiration()
                .expiration(2, TimeUnit.SECONDS)
                .build();
        map.put("1", "测试", ExpirationPolicy.CREATED, 1, TimeUnit.SECONDS);
        map.put("2", "测试", ExpirationPolicy.CREATED, 2, TimeUnit.SECONDS);
        map.put("3", "测试", ExpirationPolicy.CREATED, 999, TimeUnit.MILLISECONDS);
        map.put("4", "测试", ExpirationPolicy.CREATED, 1003, TimeUnit.MILLISECONDS);
        Thread.sleep(1002);
        System.out.println(map); // {2=测试, 4=测试}
    }

4.最大值的使用:

   /**
     * 最大值的使用:
     * Map中映射数目超过最大值的大小时,先过期第一个要过期的entity过期
     *
     * @throws InterruptedException
     */
    private static void test4() throws InterruptedException {
        ExpiringMap<String, String> map = ExpiringMap.builder()
                .maxSize(3)
                .expiration(2, TimeUnit.SECONDS)
                .build();
        map.put("1", "测试");
        map.put("2", "测试");
        map.put("3", "测试");
        System.out.println(map); // {1=测试, 2=测试, 3=测试}
        map.put("4", "测试");
        System.out.println(map); // {2=测试, 3=测试, 4=测试}
        
    }

5. 过期侦听器的使用:

    /**
     * 过期侦听器的使用:当entity过期时,可以通知过期侦听器:
     *
     * @throws InterruptedException
     */
    private static void test5() throws InterruptedException {
        ExpiringMap<String, String> map = ExpiringMap.builder()
                // 同步过期提醒
                .expirationListener((key, value) -> remindExpiration(key, value))
                // 异步过期提醒
                .asyncExpirationListener((key, value) -> remindAsyncExpiration(key, value))
                .expiration(2, TimeUnit.SECONDS)
                .build();
        map.put("1", "测试");
        while (true){

        }

    }

    /**
     * 过期提醒
     *
     * @param key
     * @param value
     */
    private static void remindExpiration(Object key, Object value) {
        System.out.println("过期提醒,key: " + key + " value: " + value);
    }

    /**
     * 异步过期提醒
     *
     * @param key
     * @param value
     */
    private static void remindAsyncExpiration(Object key, Object value) {
        System.out.println("异步过期提醒,key: " + key + " value: " + value);
    }

6.懒加载的使用:

    /**
     * 懒加载的使用:put方法时不创建对象,在调用get方法时自动去创建对象
     *
     * @throws InterruptedException
     */
    private static void test6() throws InterruptedException {
        ExpiringMap<String, Student> map = ExpiringMap.builder()
                .expiration(2, TimeUnit.SECONDS)
                .entryLoader(name -> new Student(name))
                .build();
        System.out.println(map); // {}
        map.get("hanxiaozhang");
        System.out.println(map); // {hanxiaozhang=com.hanxiaozhang.expiringmap.ExpiringMapTest$Student@5d6f64b1}
    }

7. 其他:

   /**
     * 其他:
     *
     * @throws InterruptedException
     */
    private static void test7() throws InterruptedException {
        ExpiringMap<String, String> map = ExpiringMap.builder()
                .expiration(2, TimeUnit.SECONDS)
                .build();
        map.put("1", "测试");
        // 查看剩余过期时间:
        long remainExpiration = map.getExpectedExpiration("1");
        System.out.println("查看剩余过期时间:" + remainExpiration);  // 查看剩余过期时间:1970
        // 查看设置过期时间:
        long setExpiration = map.getExpiration("1");
        System.out.println("查看设置过期时间:" + setExpiration);  // 查看设置过期时间:2000
        // 重置过期时间
        map.resetExpiration("1");
        System.out.println("查看剩余过期时间:" + map.getExpectedExpiration("1")); // 查看剩余过期时间:1999

    }