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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • FASTAI_AI领域

    FASTAI_AI领域Fastai简介在深度学习领域,最受学生欢迎的MOOC课程平台有三个:Fast.ai、deeplearning.ai/Coursera和Udacity。Fastai作为其中之一,是一个课程平台,一个讨论社区,也是一个PyTorc的顶层框架。Fastai的理念就是:Makingneuralnetsuncoolagain,让神经网络没那么望而生畏,其课程也是采用项目驱动的方式教学。经过Fa…

    2025年10月2日
    3
  • Mac的pycharm中快捷键command+a不能全选「建议收藏」

    Mac的pycharm中快捷键command+a不能全选「建议收藏」问题:今天在pycharm中想使用快捷键全选结果:command+a的时候不是全选而是showusages原因:是因为安装了ideavim插件解决方法:卸载掉ideavim插件找到这个插件ideavim卸载uninstall卸载之后提示重启,重启就ok了。…

    2022年5月9日
    135
  • javascript定义数组,将数组中数组内容求和_c语言一维数组求和

    javascript定义数组,将数组中数组内容求和_c语言一维数组求和JS数组求和的常用方法。一、for循环vararr=[1,2,3];functionsum(arr){vars=0;for(vari=0;is+=arr[i];}returns;}console.log(sum(arr));//6二、forEach遍历vararr=[1,2,3];functionsum(arr){vars=0;arr.forEach(…

    2022年9月26日
    3
  • Java吧百度贴吧,年薪60W必备

    Java吧百度贴吧,年薪60W必备思考前面提到Kafka帮我们实现了各个版本的生产者代码,其实他也可以完全不提供这份代码,因为核心的队列的功能已经实现了,这些客户端的代码也可以完全交由用户自己实现。那么假如没有官方代码,我们又该实现一些什么功能,有哪些接口,哪些方法,以及如何组织这些代码呢。带着这样的问题我们一起来思考一下!一般对于这种带有数据流转的设计,我会从由谁产生?什么数据?通往哪去?如何保证通路可靠?这几个方面来考虑。消息自然是通过应用程序构造出来并提供给生产者,生产者首先要知道需要将消息发送到哪个Bro

    2022年7月7日
    38
  • sql数据库嵌套查询_select嵌套查询

    sql数据库嵌套查询_select嵌套查询嵌套查询是将一个select查询放到另一个查询的where子句中去如:查询”xx“同学的所修课程及分数1.先选择姓名为”xx”的同学的学号select学号from学生where姓名=“XX”2.根据学号来选择相关字段select课程名,分数from成绩where学号=根据1,2合并select课程名,分数from成绩where学号=(select学号from…

    2022年8月10日
    12
  • .9图片报错Execution failed for task ‘:app:mergeDebugResources’. > Crunching Cruncher scrollbar_thumb.9.p

    .9图片报错Execution failed for task ‘:app:mergeDebugResources’. > Crunching Cruncher scrollbar_thumb.9.p

    2021年9月30日
    45

发表回复

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

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