Java如何设置过期时间的map的几种方法

目录
  • 一、技术背景
  • 二、技术效果
  • 三、ExpiringMap
    • 3.1功能简介
    • 3.2源码
    • 3.3示例
  • 四、LoadingCache
    • 4.1功能简介
    • 4.2示例
    • 4.3移除机制
    • 4.4其他
  • 五、HashMap的封装

一、技术背景

在实际的项目开发中,我们经常会使用到缓存中间件(如redis、MemCache等)来帮助我们提高系统的可用性和健壮性。

但是很多时候如果项目比较简单,就没有必要为了使用缓存而专门引入Redis等等中间件来加重系统的复杂性。那么Java本身有没有好用的轻量级的缓存组件呢。

答案当然是有喽,而且方法不止一种。常见的解决方法有:ExpiringMap、LoadingCache及基于HashMap的封装三种。

二、技术效果

  • 实现缓存的常见功能,如过时删除策略
  • 热点数据预热

三、ExpiringMap

3.1 功能简介

  • 可设置Map中的Entry在一段时间后自动过期。
  • 可设置Map最大容纳值,当到达Maximum size后,再次插入值会导致Map中的第一个值过期。
  • 可添加监听事件,在监听到Entry过期时调度监听函数。
  • 可以设置懒加载,在调用get()方法时创建对象。

3.2 源码

github地址

3.3 示例

添加依赖(Maven)

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

示例源码

public class ExpiringMapApp {

    public static void main(String[] args) {
        // maxSize: 设置最大值,添加第11个entry时,会导致第1个立马过期(即使没到过期时间)
        // expiration:设置每个key有效时间10s, 如果key不设置过期时间,key永久有效。
        // variableExpiration: 允许更新过期时间值,如果不设置variableExpiration,不允许后面更改过期时间,一旦执行更改过期时间操作会抛异常UnsupportedOperationException
        // policy:
        //        CREATED: 只在put和replace方法清零过期时间
        //        ACCESSED: 在CREATED策略基础上增加, 在还没过期时get方法清零过期时间。
        //        清零过期时间也就是重置过期时间,重新计算过期时间.
        ExpiringMap<String, String> map = ExpiringMap.builder()
            .maxSize(10)
            .expiration(10, TimeUnit.SECONDS)
            .variableExpiration().expirationPolicy(ExpirationPolicy.CREATED).build();

        map.put("token", "lkj2412lj1412412nmlkjl2n34l23n4");
        map.put("name", "管理员", 20000, TimeUnit.SECONDS);

        // 模拟线程等待...
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("token ===> " + map.get("token"));
        System.out.println("name ===> " + map.get("name"));

        // 注意: 在创建map时,指定的那些参数如过期时间和过期策略都是全局的, 对map中添加的每一个entry都适用.
        //        在put一个entry键值对时可以对当前entry 单独设置 过期时间、过期策略,只对当前这个entry有效.
    }
}

运行结果

token ===> null
name ===> 管理员

注意
在创建map时,指定的那些参数如过期时间和过期策略都是全局的, 对map中添加的每一个entry都适用。
在put一个entry键值对时可以对当前entry 单独设置 过期时间、过期策略,只对当前这个entry有效.

四、LoadingCache

4.1 功能简介

Google开源出来的一个线程安全的本地缓存解决方案。

特点:提供缓存回收机制,监控缓存加载/命中情况,灵活强大的功能,简单易上手的api。

4.2 示例

源码

public class LoadingCacheApp {

    public static void main(String[] args) throws Exception {
        // maximumSize: 缓存池大小,在缓存项接近该大小时, Guava开始回收旧的缓存项
        // expireAfterAccess: 设置时间对象没有被读/写访问则对象从内存中删除(在另外的线程里面不定期维护)
        // removalListener: 移除监听器,缓存项被移除时会触发的钩子
        // recordStats: 开启Guava Cache的统计功能
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
            .maximumSize(100)
            .expireAfterAccess(10, TimeUnit.SECONDS)
            .removalListener(new RemovalListener<String, String>() {
                @Override
                public void onRemoval(RemovalNotification<String, String> removalNotification) {
                    System.out.println("过时删除的钩子触发了... key ===> " + removalNotification.getKey());
                }
            })
            .recordStats()
            .build(new CacheLoader<String, String>() {
                // 处理缓存键不存在缓存值时的处理逻辑
                @Override
                public String load(String key) throws Exception {
                    return "不存在的key";
                }
            });

        cache.put("name", "小明");
        cache.put("pwd", "112345");

        // 模拟线程等待...
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("token ===> " + cache.get("name"));
        System.out.println("name ===> " + cache.get("pwd"));
    }
}

运行结果

过时删除的钩子触发了... key ===> name
token ===> 不存在的key
过时删除的钩子触发了... key ===> pwd
name ===> 不存在的key

4.3 移除机制

guava做cache时候数据的移除分为被动移除和主动移除两种。

被动移除

  • 基于大小的移除:数量达到指定大小,会把不常用的键值移除
  • 基于时间的移除:expireAfterAccess(long, TimeUnit) 根据某个键值对最后一次访问之后多少时间后移除。expireAfterWrite(long, TimeUnit) 根据某个键值对被创建或值被替换后多少时间移除
  • 基于引用的移除:主要是基于java的垃圾回收机制,根据键或者值的引用关系决定移除

主动移除

  • 单独移除:Cache.invalidate(key)
  • 批量移除:Cache.invalidateAll(keys)
  • 移除所有:Cache.invalidateAll()

如果配置了移除监听器RemovalListener,则在所有移除的动作时会同步执行该listener下的逻辑。

如需改成异步,使用:RemovalListeners.asynchronous(RemovalListener, Executor).

4.4 其他

  • 在put操作之前,如果已经有该键值,会先触发removalListener移除监听器,再添加
  • 配置了expireAfterAccess和expireAfterWrite,但在指定时间后没有被移除。
  • 删除策略逻辑:

CacheBuilder构建的缓存不会在特定时间自动执行清理和回收工作,也不会在某个缓存项过期后马上清理,它不会启动一个线程来进行缓存维护,因为首先线程相对较重,其次某些环境限制线程的创建。

它会在写操作时顺带做少量的维护工作,或者偶尔在读操作时做。当然,也可以创建自己的维护线程,以固定的时间间隔调用Cache.cleanUp()。

五、HashMap的封装

我们可以参考上面两个工具包的思路,自己封装一个可以设置过时时间的HashMap来实现我们想要的效果。

到此这篇关于Java如何设置过期时间的map的几种方法的文章就介绍到这了,更多相关Java 过期时间map内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java缓存Map设置过期时间实现解析

    这篇文章主要介绍了Java缓存Map设置过期时间实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言 最近项目需求需要一个类似于redis可以设置过期时间的K,V存储方式.项目前期暂时不引进redis,暂时用java内存代替. 解决方案 1. ExpiringMap 功能简介 : 1.可设置Map中的Entry在一段时间后自动过期. 2.可设置Map最大容纳值,当到达Maximum size后,再次插入值会导致Map中的第一个值过期.

  • Java如何设置过期时间的map的几种方法

    目录 一.技术背景 二.技术效果 三.ExpiringMap 3.1功能简介 3.2源码 3.3示例 四.LoadingCache 4.1功能简介 4.2示例 4.3移除机制 4.4其他 五.HashMap的封装 一.技术背景 在实际的项目开发中,我们经常会使用到缓存中间件(如redis.MemCache等)来帮助我们提高系统的可用性和健壮性. 但是很多时候如果项目比较简单,就没有必要为了使用缓存而专门引入Redis等等中间件来加重系统的复杂性.那么Java本身有没有好用的轻量级的缓存组件呢.

  • java操作Redis缓存设置过期时间的方法

    关于Redis的概念和应用本文就不再详解了,说一下怎么在java应用中设置过期时间. 在应用中我们会需要使用redis设置过期时间,比如单点登录中我们需要随机生成一个token作为key,将用户的信息转为json串作为value保存在redis中,通常做法是: //生成token String token = UUID.randomUUID().toString(); //把用户信息写入redis jedisClient.set(REDIS_USER_SESSION_KEY + ":"

  • Asp 操作Cookies(包括设置[赋值]、读取、删除[设置过期时间])

    例子: 复制代码 代码如下: Response.Cookies("letwego")("visiter")="84ww" '赋值 Response.Cookies("letwego").Expires= (now() 7) '设置过期时间(7天) userName=Request.Cookies("letwego")("visiter") '取Cookies Response.Cooki

  • Redis 如何批量设置过期时间(PIPLINE的使用)

    合理的使用缓存策略对开发同学来讲,就好像孙悟空习得自在极意功一般~ Redis如何批量设置过期时间呢? 不要说在foreach中通过set()函数批量设置过期时间 我们引入redis的PIPLINE,来解决批量设置过期时间的问题. PIPLINE的原理是什么? 未使用pipline执行N条命令 使用pipline执行N条命令 通过图例可以很明显的看出来PIPLINE的原理: 客户端通过PIPLINE拼接子命令,只需要发送一次请求,在redis收到PIPLINE命令后,处理PIPLINE组成的命令

  • C#实现给PDF文档设置过期时间

    目录 引入dll程序集 添加过期时间 实现代码 C# VB.NET 效果图 我们可以给一些重要文档或者临时文件设置过期时间和过期信息提示来提醒读者或管理者文档的时效性,并及时对文档进行调整.更新等.下面,分享通过C#程序代码来给PDF文档设置过期时间的方法. 引入dll程序集 [方法1]通过 NuGet 安装. 可以在Visual Studio中打开“解决方案资源管理器”,鼠标右键点击“引用”,“管理NuGet包”,然后搜索“Free Spire.PDF”,点击“安装”. 也可以将以下内容复制到

  • 本地存储localStorage设置过期时间示例详解

    目录 思考 实现思路 代码实现 代码测试 思考 在我们使用cookie的时候是可以设置有效期的,但是localStorage本身是没有该机制的,只能人为的手动删除,否则会一直存放在浏览器当中,可不可以跟cookie一样设置一个有效期.如果一直存放在浏览器又感觉有点浪费,那我们可以把localStorage进行二次封装实现该方案. 实现思路 在存储的时候设置一个过期时间,并且存储的数据进行格式化方便统一校验,在读取的时候获取当前时间进行判断是否过期,如果过期进行删除即可. 代码实现 目录结构 en

  • Java读取Map的两种方法与对比

    前言 在java中遍历Map有不少的方法.这篇文章我们就来看一下Java读取Map的两种方法以及这两种方法的对比. 一. 遍历Map方法A Map map = new HashMap(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); Object key = entry.getKey(); Object val = en

  • java 遍历MAP的几种方法示例代码

    java中遍历MAP的几种方法 Map<String,String> map=new HashMap<String,String>(); map.put("username", "qq"); map.put("passWord", "123"); map.put("userID", "1"); map.put("email", "qq

  • java遍历Map的几种方法分析

    本文实例分析了java遍历Map的几种方法.分享给大家供大家参考,具体如下: Java代码: Map<String,String> map=new HashMap<String,String>(); map.put("username", "qq"); map.put("passWord", "123"); map.put("userID", "1"); map.

随机推荐