深入探讨Guava的缓存机制

news2024/11/27 0:45:05

第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>() {
                            @Override
                            public 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> {
  @Override
  public 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>() {
            @Override
            public 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.coloradmin.cn/o/1287120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【开源】基于JAVA的城市桥梁道路管理系统

项目编号&#xff1a; S 025 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S025&#xff0c;文末获取源码。} 项目编号&#xff1a;S025&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询城市桥…

数据结构(超详细讲解!!)第二十六节 图(中)

1.存储结构 1.邻接矩阵 图的邻接矩阵表示法&#xff08;Adjacency Matrix&#xff09;也称作数组表示法。它采用两个数组来表示图&#xff1a; 一个是用于存储顶点信息的一维数组&#xff1b;另一个是用于存储图中顶点之间关联关系的二维数组&#xff0c;这个关联关系数组被…

基于ROPNet项目训练modelnet40数据集进行3d点云的配置

项目地址&#xff1a; https://github.com/zhulf0804/ROPNet 在 MVP Registration Challenge (ICCV Workshop 2021)&#xff08;ICCV Workshop 2021&#xff09;中获得了第二名。项目可以在win10环境下运行。 论文地址&#xff1a; https://arxiv.org/abs/2107.02583 网络简介…

vue2项目中添加字体文件

vue2项目中添加字体文件 1、下载相关文件&#xff0c;放置文件夹中&#xff0c;这里我是在assets文件中新建了fontFamily 2、在assets文件中新建css文件 3、在页面中使用 <style lang"less" scoped> import ../../assets/css/fonts.less;.total-wrap {displa…

深度学习火车票识别系统 计算机竞赛

文章目录 0 前言1 课题意义课题难点&#xff1a; 2 实现方法2.1 图像预处理2.2 字符分割2.3 字符识别部分实现代码 3 实现效果4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 图像识别 火车票识别系统 该项目较为新颖&#xff0c;适…

详细介绍如何使用 SSD 进行实时物体检测:单次 MultiBox 探测器-含源码

介绍 在实时对象检测中,主流范例传统上采用多步骤方法,包括边界框、像素或特征重采样以及高质量分类器应用的提议。虽然这种方法已经实现了高精度,但其计算需求往往阻碍了其对实时应用的适用性。然而,单次多框检测器 (SSD) 代表了基于深度学习的对象检测的突破性飞跃。SSD…

rust中动态数组Vec的简单使用

在Rust中&#xff0c;Vector&#xff08;简称Vec&#xff09;是一个动态数组数据结构&#xff0c;它可以动态地增加或减少其容量。Vec是Rust标准库中的一个常见类型&#xff0c;非常适合用于存储和操作一系列相同类型的值。 Vec其实是一个智能指针&#xff0c;用于在堆上分配内…

自定义软件app定制开发的需求和趋势|企业网站小程序搭建

自定义软件app定制开发的需求和趋势|企业网站小程序搭建 随着智能手机的普及和移动互联网的快速发展&#xff0c;移动应用程序&#xff08;App&#xff09;成为人们日常生活和工作中必不可少的一部分。然而&#xff0c;市面上已有的应用程序并不能完全满足用户的个性化需求&…

编写测试用例的17个技巧

1、前言 测试用例是任何测试周期的第一步&#xff0c;对任何项目都非常重要。如果在此步骤中出现任何问题&#xff0c;则在整个软件测试过程中都会扩大影响。如果测试人员在创建测试用例模板时使用正确的过程和准则&#xff0c;则可以避免这种情况。 在本文中将分享一些简单而…

synchronized底层原理(一)

文章目录 1. 问题引入2. 相关概念3. Synchronized使用4. Synchronized底层原理1. 简介2. Monitor&#xff08;管程/监视器&#xff09;3. Java语言的内置管程synchronized4. Java对象的内存布局5. 如何使用MarkWord记录锁状态6. 偏向锁7. 轻量级锁 1. 问题引入 假设我们有1000…

PostGIS学习教程十:空间索引

PostGIS学习教程十&#xff1a;空间索引 回想一下&#xff0c;空间索引是空间数据库的三个关键特性之一。空间索引使得使用空间数据库存储大型数据集成为可能。在没有空间索引的情况下&#xff0c;对要素的任何搜索都需要对数据库中的每条记录进行"顺序扫描"。索引通…

在gitlab中使用gitlab-sshd替换ssh服务

参考&#xff1a;https://docs.gitlab.com/ee/administration/operations/gitlab_sshd.html 说明 gitlab-sshd 是 OpenSSH 的轻量级替代品&#xff0c;用于提供 SSH 操作。虽然 OpenSSH 使用受限的 shell 方法&#xff0c;但 gitlab-sshd 的行为更像是一个现代的多线程服务器应…

mabatis基于xml方式和注解方式实现多表查询

前面步骤 http://t.csdnimg.cn/IPXMY 1、解释 在数据库中&#xff0c;单表的操作是最简单的&#xff0c;但是在实际业务中最少也有十几张表&#xff0c;并且表与表之间常常相互间联系&#xff1b; 一对一、一对多、多对多是表与表之间的常见的关系。 一对一&#xff1a;一张…

【Maven】安装和使用

1. Maven 概述 Maven 是一款用于管理和构建 java 项目的工具&#xff0c;可以进行依赖管理、统一项目结构和项目构建。 1.1 Maven 模型 项目对象模型 (Project Object Model)依赖管理模型(Dependency)构建生命周期/阶段(Build lifecycle & phases) 1.2 Maven 仓库 仓库的…

ROS2教程01 ROS2介绍

ROS2介绍 版权信息 Copyright 2023 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. The author holds all right…

高级搜索——伸展树Splay详解

文章目录 伸展树Splay伸展树Splay的定义局部性原理Splay的伸展操作逐层伸展双层伸展zig-zig/zag-zagzig-zag/zag-zigzig/zag双层伸展的效果与效率 伸展树的实现动态版本实现递增分配器节点定义Splay类及其接口定义伸展操作左单旋右单旋右左/左右双旋伸展 查找操作删除操作插入操…

【laBVIEW学习】4.声音播放,自定义图标,滚动条设置,保存参数以及恢复参数

一。声音播放&#xff08;报错&#xff0c;未实现&#xff09; 1.报错4810 2.解决方法&#xff1a; 暂时未解决。 二。图片修改 1.目标&#xff1a;灯泡---》自定义灯泡 2.步骤&#xff1a; 1.右键点击--》自定义运行 表示可以制作自定义类型 2.右键--》打开自定义类型 这样就…

【Qt开发流程】之对象模型2:属性系统

描述 Qt提供了一个复杂的属性系统&#xff0c;类似于一些编译器供应商提供的属性系统。然而&#xff0c;作为一个独立于编译器和平台的库&#xff0c;Qt不依赖于非标准的编译器特性&#xff0c;如__property或[property]。 Qt解决方案适用于Qt支持的所有平台上的任何标准c编译…

java的GUI基础使用

java.awt包提供了基本的GUI设计工具&#xff0c;主要包括组件&#xff08;Component&#xff09;、容器&#xff08;Container&#xff09;和布局管理器&#xff08;LayoutManager&#xff09;&#xff1b; Java的图形用户界面的最基本组成部分是组件&#xff08;Component&…

Hadoop学习笔记(HDP)-Part.11 安装Kerberos

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …