java中实现缓存的几种方式

一、通过HashMap实现缓存

这种方式可以简单实现本地缓存,但是实际开发中不推荐使用,下面我们来实现一下这种方式。
首先创建一个管理缓存的类

public class LocalCache {public static ConcurrentMap<String,String> cache = new ConcurrentHashMap<>();static {String name = 1 + "-" + UUID.randomUUID().toString();LocalCache.cache.put("1",name);System.out.println("id为"+1+"的数据添加到了缓存");}
}

这个类中有一个静态代码块,静态代码块会在类加载时就执行,我们可以在这里完成对缓存的初始化,决定缓存内一开始就有哪些数据,另外我们还可以把这个类交给spring来管理。

@Component
public class LocalCache {public static ConcurrentMap<String,String> cache = new ConcurrentHashMap<>();static {String name = 1 + "-" + UUID.randomUUID();LocalCache.cache.put("1",name);System.out.println("id为"+1+"的数据添加到了缓存");}@PostConstructpublic void init(){String name = 2 + "-" + UUID.randomUUID().toString();LocalCache.cache.put("2",name);System.out.println("id为"+2+"的数据添加到了缓存");}
}

在把类交给spring管理后,在方法上加入@PostConstruct可以使这个方法默认执行
随后我们编写一个接口来测试缓存:

@RestController
@RequestMapping("/api/cache")
public class CacheTestController {@GetMapping("/test/{id}")public String test(@PathVariable Long id){String name = LocalCache.cache.get(String.valueOf(id));if (name != null){System.out.println("缓存中存在,查询缓存");System.out.println(name);return name;}System.out.println("缓存中不存在,查询数据库");name = id + "-" + UUID.randomUUID().toString();System.out.println(name);LocalCache.cache.put(String.valueOf(id),name);return name;}}

启动项目测试,控制台输出信息如下:

我们可以看到这两个初始化都被执行了,然后我们调用接口查询id为1与id为2的数据

再查询id为3的两次

可以看到我们先是生成了一次UUID存入ConcurrentHashmap,第二次查询时ConcurrentHashmap中存在了,直接从ConcurrentHashmap中获得数据,如此一来我们就实现了ConcurrentHashmap形式的本地缓存。

二、通过guava local cache实现
guava cache介绍
Guava是Google提供的一套Java工具包,而Guava Cache是一套非常完善的本地缓存机制(JVM缓存)。

Guava cache的设计来源于CurrentHashMap,可以按照多种策略来清理存储在其中的缓存值且保持很高的并发读写性能。

实际使用
首先导入依赖

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>23.0</version></dependency>

编写配置文件,这里我们创建一个五秒钟过期时间的缓存方便测试

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;@Component
public class GuavaLocalCache {private Cache<String,String> fiveSecondCache = CacheBuilder.newBuilder()//设置缓存初始大小,应该合理设置,后续会扩容.initialCapacity(10)//最大值.maximumSize(100)//并发数设置.concurrencyLevel(5)//缓存过期时间,写入后5秒钟过期.expireAfterWrite(5,TimeUnit.SECONDS)//统计缓存命中率.recordStats().build();public Cache<String, String> getFiveSecondCache() {return fiveSecondCache;}public void setFiveSecondCache(Cache<String, String> fiveSecondCache) {this.fiveSecondCache = fiveSecondCache;}}

下面我们对guava cache进行简单的使用,并尝试其中的命中率统计等功能

	@Autowiredprivate GuavaLocalCache guavaLocalCache;@RequestMapping("guavaTest")public String guavaTest(Long id){// 获取缓存Cache<String, String> fiveSecondCache = guavaLocalCache.getFiveSecondCache();// 从缓存中获取对象String nameCache = fiveSecondCache.getIfPresent(String.valueOf(id));// 缓存中存在if (nameCache != null){System.out.println("缓存命中:" + nameCache + ","+ getCacheStats(fiveSecondCache));return nameCache;}//将数据存入缓存System.out.println("缓存未命中,"+ getCacheStats(fiveSecondCache));nameCache = id + "-" + UUID.randomUUID().toString();fiveSecondCache.put(String.valueOf(id),nameCache);return nameCache;}public String getCacheStats(Cache<String, String> cache){CacheStats stats = cache.stats();return "缓存命中率:"+stats.hitRate()+"被清除缓存数:"+stats.evictionCount();}

首先访问一次id为1的数据,等5秒后再访问一次,然后立刻访问第三次

 可以看到缓存未命中两次,其中缓存过期被删除了一次,随后在5秒内立刻访问缓存命中,缓存命中率,被清除缓存数均正确,测试完成
guava cache还有许多没有测试到的功能以及各种淘汰策略和机制,各位可以尝试深入了解。

注意:1.本地缓存是jvm层面的缓存,一旦该应用重启或停止了,缓存也消失了;

2.在分布式系统中,同一个应用部署有多个,这些应用的本地缓存仅限于本地应用内部,是互不相通的,在负载均衡中,分配到处理的各个应用读取本地缓存的结果可能会存在不一致。

使用redis实现缓存

redis简介

Redis 是C语言开发的一个开源高性能键值对的内存数据库,可以用来做数据库、缓存、消息中间件等场景,是一种NoSQL(not-only sql,非关系型数据库)的数据库。

下面我们介绍在springboot项目中的使用
springboot中有redis的starter我们直接引用即可

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

然后在spring配置文件中加入如下设置,这里用的是properties形式的文件,host是部署redis的服务器ip,port是端口号,password是密码,如果没有设置密码不填即可

spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=

同样我们编写接口测试

@Autowired
private StringRedisTemplate stringRedisTemplate;@RequestMapping("/redisTest")public String redisCacheTest(Long id){String name = stringRedisTemplate.opsForValue().get(String.valueOf(id));if (name != null){System.out.println("缓存中存在,查询缓存");System.out.println(name);return name;}System.out.println("缓存中不存在,查询数据库");name = id + "-" + UUID.randomUUID().toString();System.out.println(name);stringRedisTemplate.opsForValue().set(String.valueOf(id),name);return name;}

以上就是Java三种使用缓存的方式。

redis是缓存中使用比较普遍的方案,本文不过多赘述。问题来了,如何实现比redis更快的查询速度呢。答案是本地缓存,具体在Java中可以使用ConcurrentHashMap(HashMap是线程不安全的,本文使用ConcurrentHashMap实现本地高效和安全缓存)。但是既然是缓存,肯定还要整一套删除策略、最大空间限制、刷新策略。要不然随便用,可能会导致OuOfMemory异常。好了,废话不多说,上文列举了三种,这里着重介绍下主角

Guava Cache。思路来源:想比Redis还要快,只能在数据传输上下功夫,把不同服务器之间、甚至不同进程之间的数据传输都省略掉,直接把数据放在JVM中。像redis还涉及到连接,数据传输,因此ConcurrentMap是本地缓存一个比较好的方案。Guava Cache居于此,并拥有一套完善的删除策略、最大空间限制、刷新策略机制。

但Guava Cache是JVM层面的缓存,服务停掉或重启便消失了,在分布式环境中也有其局限性,因此,比较好的缓存方案是Guava Cache+Redis双管齐下。先查询Guava Cache,命中即返回,未命中再查redis。

PS:文章参考【java缓存、redis缓存、guava缓存】java中实现缓存的几种方式_java缓存cache-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/419705.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL插入、更新和删除数据

SQL插入、更新和删除数据 一、直接向表插入数据 1.1、插入完整的行 这里所说的完整行指的是包含表内所有字段的数据行&#xff1b;假设表中有n个字段&#xff0c;则插入完整行的语法&#xff1a; INSERT INTO 表名或视图名 VALUES(字段1的值,字段2的值,字段3的值,...,字段n的…

基于Java+SpringBoot+Vue+MySQL的地方美食分享网站

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于SpringBootVue的地方美食分享网站【附源码文档】、前后…

【Redis入门到精通一】什么是Redis?

目录 Redis 1. Redis的背景知识 2.Redis特性 3.Redis的使用场景 4.Ubuntu上安装配置Redis Redis Redis在当今编程技术中的地位可以说非常重要&#xff0c;大多数互联网公司内部都在使用这个技术&#xff0c;熟练使用Redis已经成为开发人员的一个必备技能。 本章将带领读者…

JavaScript使用高德API显示地图

前言 在JavaScript中&#xff0c;使用Leaflet库显示地图是一种常见的做法。Leaflet是一个开源的JavaScript库&#xff0c;用于在Web应用程序中创建互动地图。它非常轻量级&#xff0c;易于使用&#xff0c;并且提供了多种功能&#xff0c;使开发者能够轻松地将地图集成到他们的…

“知识启航·新年新题”——2025年粉丝专属学术助力计划

一、活动背景与目的 为了感谢广大粉丝一直以来的支持与厚爱&#xff0c;我们特别推出“知识启航新年新题”2025年粉丝专属学术助力计划。本次活动旨在通过提供免费的开题报告、免费的任务书以及一系列学术指导服务&#xff0c;助力粉丝在新的一年里开启学术与项目研究的新篇章…

C# 获取系统使用情况

一个简单的小工具&#xff0c;主要用来获取当期的电脑信息以及内存的使用情况。本来也没想着写这个玩意&#xff0c;还不如随便下个相关的软件好使&#xff0c;但是前一段时间为了追查系统卡顿的问题&#xff0c;所以就加上了一段统计内存的代码&#xff0c;用来看看是否由这个…

DDComponentForAndroid:探索Android组件化方案

在现代Android应用开发中&#xff0c;随着应用规模的不断扩大&#xff0c;传统的单体应用架构已经无法满足快速迭代和维护的需求。组件化架构作为一种解决方案&#xff0c;可以将应用拆分成多个独立的模块&#xff0c;每个模块负责特定的功能&#xff0c;从而提高代码的可维护性…

PWR电源控制(低功耗模式)

1 PWR简介 1 程序后面是空循环&#xff0c;即使不用也会耗电&#xff0c;所以有了低功耗&#xff08;例如遥控器&#xff09; 2 也要保留唤醒模式&#xff0c;如串口接收数据中断唤醒&#xff0c;外部中断唤醒&#xff0c;RTC闹钟唤醒&#xff0c;在需要工作是&#xff0c;ST…

【redis】redis的特性和主要应用场景

文章目录 redis 的特性在内存中存储数据可编程的扩展能力持久化集群高可用快 redis 的应用场景实时数据存储缓存消息队列 redis 的特性 redis 的一些特性&#xff08;优点&#xff09;成就了它 在内存中存储数据 In-memory data structures MySQL 主要是通过“表”的方式来…

分享基于PDF.JS的移动端PDF阅读器代码

一、前言 在之前的文章《分享基于PDF.js的pdf阅读器代码》里提到了PC端基于PDF.js的阅读器&#xff0c;本文将提供针对移动端的版本。 二、pdfViewer 为了能够直接使用&#xff0c;这里分享一下经过简单修改后能直接使用的pdfViewer代码&#xff1a; pdfViewer代码目录&…

如何在红米手机中恢复已删除的照片?(6 种方式可供选择)

凭借出色的相机和实惠的价格&#xff0c;小米红米系列已成为全球知名品牌。但是&#xff0c;最近有些人抱怨他们在 红米设备上丢失了许多珍贵的图片或视频&#xff0c;并希望弄清楚如何从小米手机恢复已删除的照片。好吧&#xff0c;在小米设备上恢复已删除的视频/照片并不难。…

基于Pytorch框架的深度学习U2Net网络精细天空分割系统源码

第一步&#xff1a;准备数据 头发分割数据&#xff0c;总共有10276张图片&#xff0c;里面的像素值为0和1&#xff0c;所以看起来全部是黑的&#xff0c;不影响使用 第二步&#xff1a;搭建模型 级联模式 通常多个类似U-Net按顺序堆叠&#xff0c;以建立级联模型&#xff0c…

移动端视频编辑SDK解决方案,AI语音识别添加字幕

对于众多Vlog创作者而言&#xff0c;繁琐的字幕添加过程往往成为提升内容质量的绊脚石。为了彻底改变这一现状&#xff0c;美摄科技凭借其深厚的AI技术积累与创新的移动端视频编辑SDK解决方案&#xff0c;推出了革命性的AI语音识别添加字幕功能&#xff0c;让视频创作更加高效、…

【数据结构】LinkedList ------ java实现

知识框架图&#xff1a; LinkedList是一种常用的数据结构。底层是一个双向链表。每个节点包含数据以及指向前一个节点和后一个节点的引用。 一&#xff1a;LinkedList的使用 1.1 LinkedList的构造方法 方法 解释LinkedList() 无参构造public LinkedList(Collection<? exte…

免费的月考成绩发布小程序

月考成绩出炉&#xff0c;老师们便开始了一项既繁琐又耗时的工作&#xff1a;将成绩单私信给每位学生家长。需要老师们在繁忙的教学工作中抽出自己额外休息的时间&#xff0c;还要确保每位家长都能及时准确的收到自己孩子的成绩单。然而&#xff0c;随着科技的发展&#xff0c;…

Delphi5数据控制组件——查询

文章目录 效果图参考查询Free方法Close方法总结通俗理解 完整代码 效果图 参考 本文是在上一篇的基础上&#xff0c;将查询页面重新写一次。 查询 {点击查询} procedure TForm2.Button1Click(Sender: TObject); vartj,tj1,tj2,tj3,tj4,tj5,tj6,tj7:string; begin//按照工号查…

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建 首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件…

[ios]准备好app后使用xcode发布ios操作

在app代码完成后&#xff0c;点击xcode进行发布

船舶机械设备5G智能工厂物联数字孪生平台,推进制造业数字化转型

船舶机械设备5G智能工厂物联数字孪生平台&#xff0c;推进制造业数字化转型。在当今数字化浪潮推动下&#xff0c;船舶制造业正经历着前所未有的变革。为了应对市场的快速变化&#xff0c;提升生产效率&#xff0c;降低成本&#xff0c;并增强国际竞争力&#xff0c;船舶机械设…

【无人机设计与控制】旋转无人机摆锤的SDRE仿真

摘要 旋转无人机摆锤&#xff08;Double Rotor Pendulum, DRP&#xff09;系统的稳定性控制是现代飞行控制领域的一个挑战性课题。本文采用了状态依赖黎卡提方程&#xff08;SDRE&#xff09;方法对该系统进行建模和仿真&#xff0c;以实现摆锤的稳定控制。通过SDRE方法&#…