ExpiringMap使用

1,278 阅读2分钟

概述

高性能、低开销、零依赖性、线程安全的ConcurrentMap实现,一款基于内存可过期的map。
使用场景是介于redis和普通map之间,觉得redis过于重不想依赖redis,普通map又不自动过期。

1、支持设置map中key过一段时间自动过期,过期策略有按创建时间、按访问时间。
   过期策略为ExpirationPolicy.CREATED时,
   如果在过期前有更新(指有变化),过期时间会从新计算。
   如果在过期前有更新(指值未变化),过期时间不会从新计算。
2、可设置maxSize,超出再次插入会从第一个值过期
3、 过期key监听,可实现多个监听

过期策略为ExpirationPolicy.CREATED

/**
 * expiration(3000, TimeUnit.MILLISECONDS) 过期时间为3秒
 * expirationPolicy(ExpirationPolicy.CREATED) 过期策略为创建后
 *
 * @throws InterruptedException
 */
@Test
public void testCREATED() throws InterruptedException {
    ExpiringMap<String, String> map = ExpiringMap.builder().expiration(3000, TimeUnit.MILLISECONDS).
            expirationPolicy(ExpirationPolicy.CREATED)
            .build();
    map.put("testkey", "testValue");
    log.info("map={}", JSONUtil.toJsonStr(map));
    //等待3秒
    Thread.sleep(3000);
    log.info("sleep map={}", JSONUtil.toJsonStr(map));
}

执行结果:
10:53:16.256 [main] INFO util.ExpiringMapTest - map={"testkey":"testValue"}
10:53:19.264 [main] INFO util.ExpiringMapTest - sleep map={}

过期策略为ExpirationPolicy.CREATED,过期前更新

/**
 * expiration(3000, TimeUnit.MILLISECONDS) 过期时间为3秒
 * expirationPolicy(ExpirationPolicy.CREATED) 过期策略为创建后
 *
 * @throws InterruptedException
 */
@Test
public void testCREATED2() throws InterruptedException {
    ExpiringMap<String, String> map = ExpiringMap.builder().expiration(5000, TimeUnit.MILLISECONDS).
            expirationPolicy(ExpirationPolicy.CREATED)
            .build();
    map.put("testkey", "testValue2");
    log.info("map={}", JSONUtil.toJsonStr(map));
    Thread.sleep(4000);
    //模拟过期前更新值,注意这里更新的值未变化时会过期
    map.put("testkey", "testValue3");
    log.info("putmap={}", JSONUtil.toJsonStr(map));
    Thread.sleep(2000);
    log.info("过期前更新update map={}", JSONUtil.toJsonStr(map));

}
执行结果:
10:59:52.191 [main] INFO util.ExpiringMapTest - map={"testkey":"testValue2"}
10:59:56.201 [main] INFO util.ExpiringMapTest - putmap={"testkey":"testValue3"}
10:59:58.205 [main] INFO util.ExpiringMapTest - 过期前更新update map={"testkey":"testValue3"}

过期策略为ExpirationPolicy.ACCESSED

/**
 * expiration(3000, TimeUnit.MILLISECONDS) 过期时间为3秒
 * expirationPolicy(ExpirationPolicy.ACCESSED) 过期策略为访问
 *
 * @throws InterruptedException
 */
@Test
public void testACCESSED() throws InterruptedException {
    ExpiringMap<String, String> map = ExpiringMap.builder().expiration(3000, TimeUnit.MILLISECONDS).
            expirationPolicy(ExpirationPolicy.ACCESSED)
            .build();
    map.put("testkey", "testValue");
    log.info("map={}", JSONUtil.toJsonStr(map));
    Thread.sleep(2000);

    log.info("get map key={}", map.get("testkey"));
    Thread.sleep(2000);

    log.info("sleep map={}", JSONUtil.toJsonStr(map));
}

执行结果:
11:04:06.510 [main] INFO util.ExpiringMapTest - map={"testkey":"testValue"}
11:04:08.519 [main] INFO util.ExpiringMapTest - sleep map=testValue
11:04:10.522 [main] INFO util.ExpiringMapTest - sleep map={"testkey":"testValue"}

设置最大maxSize,超出再次插入会从第一个值过期

/**
 * 设置最大MaxSize=10,再次插入会从第一个值过期
 *
 * @throws InterruptedException
 */
@Test
public void testMaxSize() throws InterruptedException {
    ExpiringMap<String, String> map = ExpiringMap.builder().maxSize(10)
            .build();
    for (int i = 0; i < 10; i++) {
        map.put("key" + i, "value" + i);
    }
    log.info("key0={}", map.get("key0"));
    map.put("key100", "value100");
    log.info("key0={}", map.get("key0"));
    log.info("key1={}", map.get("key1"));
}

执行结果:
11:08:07.173 [main] INFO util.ExpiringMapTest - key0=value0
11:08:07.179 [main] INFO util.ExpiringMapTest - key0=null
11:08:07.179 [main] INFO util.ExpiringMapTest - key1=value1

过期key监听,可实现多个监听

/**
 *  过期key监听,可实现多个监听
 *
 * @throws InterruptedException
 */
@Test
public void testExpirationListener() throws InterruptedException {
    ExpiringMap<String, String> map = ExpiringMap.builder().
            expiration(3000, TimeUnit.MILLISECONDS).
            expirationListener((key, value) -> {
                log.info("过期监听1,key={},value={}", key, value);
            }).expirationListener((key, value) -> {
        log.info("过期监听2,key={},value={}", key, value);
    }).build();

    map.put("testkey", "testValue");
    log.info("map={}", JSONUtil.toJsonStr(map));
    Thread.sleep(3000);
    log.info("sleep map={}", JSONUtil.toJsonStr(map));

}

执行结果:
11:17:01.517 [main] INFO util.ExpiringMapTest - map={"testkey":"testValue"}
11:17:04.447 [ExpiringMap-Expirer] INFO util.ExpiringMapTest - 过期监听1,key=testkey,value=testValue
11:17:04.447 [ExpiringMap-Expirer] INFO util.ExpiringMapTest - 过期监听2,key=testkey,value=testValue
11:17:04.525 [main] INFO util.ExpiringMapTest - sleep map={}

引入pom

<!-- https://mvnrepository.com/artifact/net.jodah/expiringmap -->
<dependency>
   <groupId>net.jodah</groupId>
   <artifactId>expiringmap</artifactId>
   <version>0.5.8</version>
</dependency>

参考

expiringmap github