java map 缓存_缓存用于

java map 缓存_缓存用于缓存什么是缓存?平常的开发项目中,多多少少都会使用到缓存,因为一些数据我们没有必要每次查询的时候都去查询到数据库。缓存的使用场景:在Java应用中,对于访问频率高,更新少的数据,通常的方案是将这类数据加入缓存中,相对从数据库中读取,读缓存效率会有很大提升。在集群环境下,常用的分布式缓存有Redis等。但在某些业务场景上,可能不需要去搭建一套复杂的分布式缓存系统,在单机环境下,通常是会希望使用内部的缓存(LocalCache)。使用map缓存方案:基于ConcurrentHashMap实现数

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

缓存

什么是缓存?
平常的开发项目中,多多少少都会使用到缓存,因为一些数据我们没有必要每次查询的时候都去查询到数据库。

缓存的使用场景:
在Java应用中,对于访问频率高,更新少的数据,通常的方案是将这类数据加入缓存中,相对从数据库中读取,读缓存效率会有很大提升。
在集群环境下,常用的分布式缓存有Redis等。但在某些业务场景上,可能不需要去搭建一套复杂的分布式缓存系统,在单机环境下,通常是会希望使用内部的缓存(LocalCache)。

使用map缓存

方案:

  • 基于ConcurrentHashMap实现数据缓存,实现线程安全要求
  • SoftReference:当内存不够的时候,GC会回收SoftReference所引用的对象

SoftReference是软引用,它保存的对象实例,除非JVM即OutOfMemory,否则不会被GC回收。这个特性使得它特别适合设计对象Cache。对于Cache,我们希望被缓存的对象最好始终常驻内存,但是如果JVM内存吃紧,为了不发生OutOfMemoryError导致系统崩溃,必要的时候也允许JVM回收Cache的内存,待后续合适的时机再把数据重新Load到Cache中。这样可以系统设计得更具弹性。

代码如下:

/** * 使用map做缓存 */
public class MapCache { 
   
	//定义扫描时间参数
    private static final int CLEAN_TIME_PARAMETER = 5;

    private final ConcurrentHashMap<String, SoftReference<CacheObject>> cache = new ConcurrentHashMap<>();

	/** * 在构造函数中,创建一个守护程序线程,每5秒扫描一次并清理过期的对象。 */
    public MapCache(){ 
   
        Thread cleanerThread = new Thread(()->{ 
   
            //获取线程中断状态
            while (!Thread.currentThread().isInterrupted()) { 
   
                try { 
   
                    Thread.sleep(CLEAN_TIME_PARAMETER * 1000);
                    cache.entrySet().removeIf(entry ->
                            Optional.ofNullable(entry.getValue())
                                    .map(SoftReference::get)
                                    .map(CacheObject::isExpired)
                                    .orElse(false));
                } catch (InterruptedException e) { 
   
                    Thread.currentThread().interrupt();
                }
            }
        });
        cleanerThread.setDaemon(true);
        cleanerThread.start();
    }

    public void add(String key, Object value, long periodInMillis) { 
   
        if(key == null){ 
   
            return;
        }
        if(value == null){ 
   
            cache.remove(key);
        }else { 
   
            long expiryTime = System.currentTimeMillis() + periodInMillis;
            cache.put(key, new SoftReference<>(new CacheObject(value, expiryTime)));
        }
    }

    public void remove(String key) { 
   
        cache.remove(key);
    }

    public Object get(String key) { 
   
        return Optional.ofNullable(cache.get(key)).map(SoftReference::get).filter(cacheObject -> !cacheObject.isExpired()).map(CacheObject::getValue).orElse(null);
    }

    public void clear() { 
   
        cache.clear();
    }

    public long size() { 
   
        return cache.entrySet().stream().filter(entry -> Optional.ofNullable(entry.getValue()).map(SoftReference::get).map(cacheObject -> !cacheObject.isExpired()).orElse(false)).count();
    }


    /** * 缓存对象value */
    private static class CacheObject { 
   
        private Object value;
        private long expiryTime;

        private CacheObject(Object value, long expiryTime) { 
   
            this.value = value;
            this.expiryTime = expiryTime;
        }

        boolean isExpired() { 
   
            return System.currentTimeMillis() > expiryTime;
        }

        public Object getValue() { 
   
            return value;
        }

        public void setValue(Object value) { 
   
            this.value = value;
        }
    }
}

测试类:

public class Test { 
   
    public static void main(String[] args) throws InterruptedException { 
   
        MapCache mapCache = new MapCache();
        mapCache.add("10001", "111111", 5 * 1000);
        mapCache.add("10002", "222222", 5 * 1000);
        mapCache.add("10003", "333333", 5 * 1000);
        System.out.println("从缓存中取出值:" + mapCache.get("10001"));
        Thread.sleep(5000L);
        System.out.println("5秒钟过后");
        // 5秒后数据自动清除了
        System.out.println("从缓存中取出值:" + mapCache.get("10001"));
     
    }
}

Optional类

关于Optional类,是jdk1.8引进的新特性,主要解决的问题是臭名昭著的空指针异常(NullPointerException)
参考文章:Optional类的学习,理解,使用

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/188445.html原文链接:https://javaforall.net

(0)
上一篇 2026年4月16日 下午4:40
下一篇 2026年4月16日 下午4:46


相关推荐

  • provided和compile的区别

    provided和compile的区别gradleprovid 和 compile 的区别在于 1 compile 假如你的 jar 包存在代码依赖性 在编译 运行时候需要依赖代码 那就用 compile2 provided 假如你的 jar 包存在代码依赖性 但是只在编译的时候需要用 而运行时不需要 例如运行时会去使用机器中 system framework 中的 jar 那就使用 provided

    2026年3月18日
    2
  • java数组删除元素_java中删除 数组中的指定元素方法[通俗易懂]

    java数组删除元素_java中删除 数组中的指定元素方法[通俗易懂]java中删除数组中的指定元素要如何来实现呢,如果各位对于这个算法不是很清楚可以和小编一起来看一篇关于java中删除数组中的指定元素的例子。java的api中,并没有提供删除数组中元素的方法。虽然数组是一个对象,不过并没有提供add()、remove()或查找元素的方法。这就是为什么类似ArrayList和HashSet受欢迎的原因。不过,我们要感谢ApacheCommonsUtils,我…

    2022年8月11日
    14
  • DHT和一致性哈希算法总结

    DHT和一致性哈希算法总结 Hash算法比较重要的考量点有两个:1.单调性(新增或者减少映射节点时,尽量不影响原有映射关系)2.平衡性(尽量均匀分布) 分布式领域常见负载均衡算法:(1)取余法:%n如果有3个节点,Hash之后取模求余 Hash(x)%3,如果加一个节点,则Hash(x)%4。 这种方法带来的问题:1一个cache服务器mdown掉了(在实际应用中必…

    2022年7月27日
    7
  • 腾讯正式发布混元3D 3.0模型

    腾讯正式发布混元3D 3.0模型

    2026年3月12日
    4
  • MySql删除重复数据(只保留一条)

    MySql删除重复数据(只保留一条)MySql 删除重复数据 1 问题引入前一段遇到 MySql 数据重复的问题 由于重复向同一张表导入同一批数据 导致前台展示的数据重复 唯一方便快捷的方法莫过于利用 delete 操作删除重复数据 已经封板发布 只保留其中一条数据 但真的是书到用时方恨少 技术也如此 当时只好在网上搜索资源 最终解决了燃眉之急 但是对找到的 delete 语句并不是太理解 后来抽时间自己研究了一下 现在稍微理解了一点 分享给大家 希望对大家有帮助 2 数据准备创建表 CREATETABLEt del repeti

    2026年3月18日
    2
  • FlashFXP 3.6 Final(正式版)注册码

    FlashFXP 3.6 Final(正式版)注册码昨天登陆FTP提示是否要升级,也没有注意点了下同意,结果升级后是最新英文版本的,把原来的资料也给丢了,忙了半天一看原来的注册码已经不好使用,在网上搜索下,找到一个可以使用的注册码和大家分享下:———————————————————FLASHFXPxgA9UrTnxgAAAAC7W5MNJwTnsl73n0Vuu1AePJgEAG41mgSvHSiDWi1Kg8B5xJNCCCAVCMr9R

    2022年7月26日
    20

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号