深入探讨Guava的缓存机制

第1章:引言

大家好,我是小黑,今天咱们聊聊Google Guava的缓存机制。缓存在现代编程中的作用非常大,它能提高应用性能,减少数据库压力,简直就是性能优化的利器。而Guava提供的缓存功能,不仅强大而且使用起来非常灵活。

在咱们深入挖掘之前,先简单说说缓存。缓存,其实就是一种保存数据的手段,目的是在未来的数据请求中,能快速地提供数据。想象一下,如果每次处理相同的数据请求都要去数据库里翻一遍,那效率岂不是很低?缓存就是在这里发挥作用,帮我们节省时间和资源。

第2章:Guava缓存机制概述

现在咱们来聊聊Guava缓存的精髓所在。Guava的缓存机制是建立在这样一个思想上:简单、快速、灵活。它不是要替代其他缓存方案,比如Redis或Memcached,而是提供一个轻量级的本地缓存方案,特别适用于那些对缓存一致性要求不高,但又希望减少对外部存储访问的场景。

Guava缓存与传统的Java缓存有什么不同呢?首先,它更加智能。例如,Guava的缓存可以自动加载新值,也可以根据需求自动刷新缓存,减少了手动管理缓存的麻烦。此外,Guava还提供了各种灵活的配置选项,比如过期策略、最大容量限制等,让你可以根据实际需要灵活地调整缓存行为。

那么,这种缓存是怎么工作的呢?基本上,Guava的缓存机制围绕几个核心组件展开:CacheBuilder、LoadingCache、Cache和CacheLoader。CacheBuilder是构建缓存的起点,它提供了一系列链式方法来配置缓存。LoadingCache和Cache是两种缓存实现,前者自动加载缓存,后者需要手动加载。CacheLoader则是定义数据加载逻辑的地方。

来看个简单的代码示例,了解如何创建和使用Guava缓存:

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;public class GuavaCacheExample {public static void main(String[] args) {// 创建缓存LoadingCache<String, String> cache = CacheBuilder.newBuilder().maximumSize(100) // 最大缓存项数.build(new CacheLoader<String, String>() {@Overridepublic String load(String key) {return fetchDataFromDatabase(key); // 模拟从数据库加载数据}});// 使用缓存try {String value = cache.get("key1"); // 获取缓存,若无则自动加载System.out.println("Value for key1: " + value);} catch (Exception e) {e.printStackTrace();}}private static String fetchDataFromDatabase(String key) {// 模拟数据库操作return "Data for " + key;}
}

第3章:Guava缓存的核心组件

Guava提供了几个非常实用的组件,它们是CacheBuilder、LoadingCache、Cache和CacheLoader。这些组件共同工作,让咱们的缓存管理变得既灵活又高效。

3.1 CacheBuilder

首先,让咱们看看CacheBuilder。这个类真是太棒了,它像个万能工具,帮你构建出各种定制的缓存。想要限制缓存大小?没问题。想要设置过期时间?一样行。它就像乐高积木,可以根据需求搭建出你想要的缓存结构。下面是个示例,展示了如何使用CacheBuilder创建一个简单的缓存:

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder().maximumSize(1000).expireAfterWrite(10, TimeUnit.MINUTES).removalListener(MY_LISTENER).build(new CacheLoader<Key, Graph>() {public Graph load(Key key) throws AnyException {return createExpensiveGraph(key);}});

在这段代码中,小黑创建了一个最大容量为1000的缓存,设置了10分钟的写入过期时间,并且还添加了一个移除监听器。

3.2 LoadingCache和Cache

接下来是LoadingCache和Cache。这两个接口真是让人爱不释手。LoadingCache可以自动加载缓存,当你尝试获取一个缓存项时,如果它不存在,Guava就会自动调用你定义的加载函数去获取数据。而Cache则更灵活,它允许你手动控制何时加载数据。

String graph = graphs.getUnchecked(key);

这段代码演示了如何从LoadingCache中获取数据。如果key对应的数据不存在,Guava会自动调用CacheLoader来加载数据。

3.3 CacheLoader

最后,但同样重要的是CacheLoader。这个抽象类定义了数据加载的逻辑。你只需要实现load方法,当缓存中没有对应的数据时,Guava就会调用它来加载新数据。

public class MyCacheLoader extends CacheLoader<Key, Graph> {@Overridepublic Graph load(Key key) {return fetchData(key); // 你的数据加载逻辑}
}

在这个例子中,小黑创建了一个CacheLoader子类,实现了加载数据的逻辑。

通过这些组件的组合,咱们可以灵活地创建出各种强大的缓存解决方案,满足不同的业务需求。Guava的缓存机制不仅强大,而且非常灵活和高效!

第4章:Guava缓存的实际应用

Guava的缓存不仅仅是理论上的高大上,它在实战中更是大放异彩。让我们看看如何将这些理论知识转化为实际的代码,解决真正的问题。

首先,想象一下这样一个场景:咱们需要从数据库中获取用户信息,但是频繁的数据库查询会导致性能问题。这时,Guava的缓存就能大显身手了。下面是一个使用Guava缓存来优化数据库查询的示例:

// 创建一个简单的缓存,用于存储用户信息
LoadingCache<String, User> userCache = CacheBuilder.newBuilder().maximumSize(100) // 设置最大缓存项数.expireAfterWrite(10, TimeUnit.MINUTES) // 设置写入后的过期时间.build(new CacheLoader<String, User>() {@Overridepublic User load(String userId) throws Exception {return getUserFromDatabase(userId); // 数据库查询逻辑}});// 使用缓存获取用户信息
public User getUser(String userId) {try {return userCache.get(userId); // 尝试从缓存获取,缓存不存在时自动加载} catch (ExecutionException e) {throw new RuntimeException("Error fetching user from cache", e);}
}private User getUserFromDatabase(String userId) {// 这里是从数据库获取用户的逻辑// 假设这是一个耗时的操作return new User(userId, "name", "email");
}

在这个例子里,小黑创建了一个LoadingCache,它在缓存中自动管理用户信息。当需要用户信息时,首先尝试从缓存中获取,如果缓存中没有,则自动调用getUserFromDatabase方法去数据库中查询并加载数据。这样,就大大减少了对数据库的访问次数,提高了应用的性能。

再来说说缓存策略。Guava提供了很多灵活的缓存策略,例如基于容量、定时过期和基于引用的回收等。这些策略可以帮助咱们灵活地管理缓存,满足不同场景的需求。比如,在一个内存敏感的应用中,咱们可能会采用软引用或弱引用缓存,这样当内存不足时,缓存可以被垃圾回收器回收,避免内存泄漏。

第5章:Guava缓存的高级特性和技巧

Guava的缓存不仅基础强大,而且提供了许多高级功能,可以帮助咱们更精细地控制缓存行为。

5.1 过期策略

首先来聊聊过期策略。Guava提供了两种类型的过期策略:基于时间的过期和基于访问的过期。基于时间的过期可以细分为写入过期和访问过期。写入过期意味着从最后一次写入开始计时,一旦超过设定时间,缓存项就会过期。而访问过期则是从最后一次读或写开始计时。

Cache<String, String> cache = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) // 写入过期.expireAfterAccess(5, TimeUnit.MINUTES) // 访问过期.build();

在这个代码中,小黑设置了一个缓存项在写入10分钟后过期,或者在最后一次访问5分钟后过期。

5.2 弱引用和软引用缓存

接下来是弱引用和软引用缓存。这两种缓存方式在处理大型对象和敏感内存环境时特别有用。软引用缓存项在内存不足时会被垃圾回收器回收,而弱引用缓存项则在垃圾回收时总会被回收。

Cache<String, BigObject> softCache = CacheBuilder.newBuilder().softValues().build();Cache<String, BigObject> weakCache = CacheBuilder.newBuilder().weakValues().build();

在这里,小黑创建了两个缓存,一个用软引用存储大对象,另一个用弱引用。

5.3 显式清除和自动清除策略

Guava还支持显式清除和自动清除策略。显式清除是指手动移除缓存项,而自动清除则是基于某些条件自动移除。

cache.invalidate(key); // 显式清除单个键
cache.invalidateAll(keys); // 显式清除多个键
cache.invalidateAll(); // 清除所有缓存项

在这段代码中,小黑演示了如何显式地从缓存中移除对象。

通过这些高级特性和技巧,Guava的缓存不仅能处理一般的缓存需求,还能解决更复杂和特定的场景,真正实现了高效和灵活的缓存管理。

第6章:性能优化和注意事项

6.1 性能优化

首先,性能优化。Guava缓存的性能非常依赖于它的配置。比如,合理设置缓存的大小和过期时间可以显著影响性能。如果缓存太大,可能会占用过多内存;如果设置得太小,又会频繁地加载数据,导致性能下降。

Cache<String, Data> cache = CacheBuilder.newBuilder().maximumSize(1000) // 合理的最大大小.expireAfterAccess(10, TimeUnit.MINUTES) // 合适的过期时间.build();

在这段代码中,小黑设置了一个最大大小和过期时间,这两个参数都是基于对应用程序的理解和实际需求设定的。

6.2 注意事项

接下来是一些注意事项。在使用Guava缓存时,要特别注意缓存的一致性和更新策略。例如,如果缓存的数据在数据库中被修改了,缓存中的数据也需要相应更新。这就需要合理地设计缓存的刷新机制。

当使用基于引用的缓存(如软引用或弱引用)时,需要了解Java的垃圾回收机制。这类缓存可能会受到垃圾回收的影响,导致缓存项提前被清除。

Guava缓存在多线程环境中是线程安全的,但在并发高的情况下,可能会成为瓶颈。因此,在高并发场景下,合理调整并发级别是提高性能的关键。

第7章:总结

通过这些章节,咱们一起走过了Guava缓存的创建、配置、使用以及优化的全过程。咱们可以看到,Guava不仅提供了强大的缓存功能,还有各种灵活的配置选项,能够满足多样化的应用场景。

无论是在哪个领域,正确的工具能够大大提高工作效率。Guava缓存正是这样的工具,它能帮助咱们优化Java应用的性能,提高代码的可读性和可维护性。当然,像任何强大的工具一样,正确地使用Guava缓存至关重要。通过这些章节,希望咱们都能更好地理解并运用它!

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

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

相关文章

Linux 压缩、解压文件的 4 种方式。tar、gzip、gunzip、zip、unzip、7z命令使用方法

目录 1、使用 tar 命令&#xff1a; 1.1. 压缩&#xff1a; 1.2. 解压&#xff1a; 1.3. tar 命令各参数含义 2. gzip、gunzip gzip 命令&#xff1a; 压缩文件&#xff1a; 保留原始文件&#xff0c;创建压缩文件&#xff1a; 保留原始文件&#xff0c;显示压缩进度&…

正则表达式(7):转义符

正则表达式&#xff08;7&#xff09;&#xff1a;正则表达式&#xff08;5&#xff09;&#xff1a;转义符 本博文转载自 此处&#xff0c;我们来认识一个常用符号&#xff0c;它就是反斜杠 “\” 反斜杠有什么作用呢&#xff1f;先不着急解释&#xff0c;先来看个小例子。 …

golang使用es,报错Elasticsearch health check failed

今天golang代码里调用es&#xff0c;结果一直报错。报错内容 ElasticsearchRestHealthIndicator : Elasticsearch health check failed然后又去es管理端看&#xff0c;明明节点是绿色的&#xff0c;估计是golang的这个有问题&#xff0c;时间紧迫&#xff0c;我就直接关掉了健…

侯捷C++ 程序的生前死后

生前&#xff1a;CRT startup code 看完课程&#xff0c;能够回答一下问题&#xff1a; C进入点是main()嘛&#xff1f;什么代码比main更早执行&#xff1f;什么代码在main结束后执行&#xff1f;为什么上述代码可以如此行为&#xff1f;Heap的结构如何&#xff1f;I/O的结构…

日志门面slf4j和各日志框架

简介 简单日志门面(Simple Logging Facade For Java) SLF4J主要是为了给Java日志访问提供一套标准、规范的API框架&#xff0c; 其主要意义在于提供接口&#xff0c;具体的实现可以交由其他日志框架&#xff0c;如log4j、logback、log4j2。 对于一般的Java项目而言&#xff…

元宇宙vr党建云上实景展馆扩大党的影响力

随着科技的飞速发展&#xff0c;VR虚拟现实技术已经逐渐融入我们的日常生活&#xff0c;尤其在党建领域&#xff0c;VR数字党建展馆更是成为引领红色教育新风尚的重要载体。今天&#xff0c;就让我们一起探讨VR数字党建展馆如何提供沉浸式体验&#xff0c;助力党建工作创新升级…

轻量封装WebGPU渲染系统示例<43>- PBR材质与阴影实(源码)

原理简介: 1. 基于rendering pass graph实现。 2. WGSL Shader 基于文件系统和宏机制动态组装。 当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/PBRShadowTest.ts 当前示例运行效果: 此示例基于此渲染系统实现&a…

【C语言】【数据结构】自定义类型:结构体

引言 这是一篇对结构体的详细介绍&#xff0c;这篇文章对结构体声明、结构体的自引用、结构体的初始化、结构体的内存分布和对齐规则、库函数offsetof、以及进行内存对齐的原因、如何修改默认对齐数、结构体传参进行介绍和说明。 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&am…

手机升级到iOS15.8后无法在xcode(14.2)上真机调试

之前手机是iOS14.2的系统,在xcode上进行真机测试运行良好&#xff0c;因为想要使用Xcode的Instruments功能&#xff0c;今天将系统更新到了iOS15.8 &#xff0c;结果崩了 说是Xcode和手机系统不兼容不能进行真机测试。在网上查了好些方法&#xff0c;靠谱的就是下载相关版本的…

Centos7云服务器上安装cobalt_strike_4.7。附cobalt_strike_4.7安装包

环境这里是阿里的一台Centos7系统。 开始安装之前首先要确保自己安装了java11及以上环境。 安装java11步骤&#xff1a; sudo yum update sudo yum install java-11-openjdk-devel把服务器端&#xff08;CS工具分服务器端和客户端&#xff09;的CS安装到服务器上后给目录下的…

【Java探索之旅】我与Java的初相识(一):Java的特性与优点及其发展史

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java入门到精通 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 一. Java语言概述与优势1.1 Java的概述1.2 Java语言的优势 二. Java领域与发展史2.1 Java的使用领域2.…

【Linux20.04-qt5.12.4软件安装与初步使用-qt在Linux使用-记录-笔记】

【Linux-qt软件安装与初步使用-qt在Linux使用-记录-笔记】 1、概述2、环境说明3、步骤总结1、了解并选择自己想要安装的版本2、访问 Qt 官方网站3、在 Qt 网站上找到下载部分&#xff08;自己想下载&#xff09;4、下载完成后&#xff0c;给安装程序文件赋予执行权限。5、自动配…

《杂文选刊》明年休刊之随笔

笔者今天偶然发现&#xff0c;网民对于近期登上社交网站热搜榜的一条新闻&#xff0c;既感兴趣又觉迷惑&#xff0c;因此关注度显得较高。 荣登社交网站热搜榜的这条新闻是&#xff1a;12月4日发出“休刊启事 ”&#xff0c;在宣布“《 杂文选刊》2024年1月1日起休刊”的同时&…

django与数据库交互关于当前时间的坑

背景 在线上服务中使用时间进行数据库操作时发现异常&#xff0c;而在本地环境无法成功复现此问题&#xff0c;导致难以进行故障排查。 核心问题 view.py class XxxViewSet(viewsets.ModelViewSet):queryset Xxx.objects.with_status().order_by("status", &quo…

【组合数学】递推关系

目录 1. 递推关系建立2. 常系数齐次递推关系的求解3. 常系数非齐次递推关系的求解4. 迭代法 1. 递推关系建立 给定一个数的序列 f ( 0 ) , f ( 1 ) , . . . , f ( n ) , . . . , f (0), f(1), ..., f(n ),... , f(0),f(1),...,f(n),..., 若存在整数 n 0 n_0 n0​ &#xff…

java--LocalDate、LocalTime、LocalDateTime、ZoneId、Instant

1.为什么要学习JDK8新增的时间 LocalDate&#xff1a;代表本地日期(年、月、日、星期) LocalTime&#xff1a;代表本地时间(时、分、秒、纳秒) LocalDateTime&#xff1a;代表本地日期、时间(年、月、日、星期、时、分、秒、纳秒) 它们获取对象的方案 2.LocalDate的常用API(…

我的 CSDN 三周年创作纪念日:2020-12-12

本人大叔一枚&#xff0c;自1992年接触电脑&#xff0c;持续了30年的业余电脑发烧爱好者&#xff0c;2022年CSDN博客之星Top58&#xff0c;阿里云社区“乘风者计划”专家博主。自某不知名财校毕业后进入国有大行工作至今&#xff0c;先后任职于某分行信息科技部、电子银行部、金…

UG NX二次开发(C#)-求曲线在某一点处的法矢和切矢

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、在UG NX中创建一个曲线3、直接放代码4、测试案例1、前言 最近确实有点忙了,好久没更新博客了。今天恰好有时间,就更新下,还请家人们见谅。 今天我们讲一下如何获取一条曲线上某一条曲…

仅 CSS 阅读进度条

为了构建一个阅读进度条&#xff0c;即显示用户向下滚动时阅读文章的进度&#xff0c;很难不考虑 JavaScript。但是&#xff0c;事实证明&#xff0c;您也可以使用纯 CSS 构建阅读进度条。 从本质上讲&#xff0c;一个名为 animation-timeline 的新实验性 CSS 属性可以让你指定…

oracle 下载java之前版本

登录oracle官网&#xff1a;Oracle | Cloud Applications and Cloud Platform 点击resource 进入该页面 点击这个 出现之前版本