性能优化 - 案例篇:缓存_Guava#LoadingCache设计

文章目录

  • Pre
  • 引言
  • 1. 缓存基本概念
  • 2. Guava 的 LoadingCache
    • 2.1 引入依赖与初始化
    • 2.2 手动 put 与自动加载(CacheLoader)
      • 2.2.1 示例代码
    • 2.3 缓存移除与监听(invalidate + removalListener)
  • 3. 缓存回收策略
    • 3.1 基于容量的回收(LRU)
    • 3.2 基于时间的回收
    • 3.3 基于 JVM GC 的回收
      • 3.3.1 GC 回收引发的缓存颠簸问题
  • 4. 常见缓存算法简介
    • 4.1 FIFO(先进先出)
    • 4.2 LRU(最近最少使用)
    • 4.3 LFU(最近最不常用)
  • 5. 简易 LRU 实现——LinkedHashMap
    • 5.1 功能局限与线程安全
  • 6. 操作系统层面的预读与文件缓存
  • 7. 缓存优化的一般思路
  • 8. 缓存应用案例
  • 9. 小结

在这里插入图片描述


Pre

性能优化 - 理论篇:常见指标及切入点

性能优化 - 理论篇:性能优化的七类技术手段

性能优化 - 理论篇:CPU、内存、I/O诊断手段

性能优化 - 工具篇:常用的性能测试工具

性能优化 - 工具篇:基准测试 JMH

性能优化 - 案例篇:缓冲区


  1. 引言:解释缓存与缓冲的区别及缓存在性能优化中的重要性;
  2. 缓存基本概念:缓存的本质、应用场景、进程内 vs 进程外缓存;
  3. Guava LoadingCache(LC)示例:
    3.1 引入依赖与初始化配置;
    3.2 手动 put 与自动加载(CacheLoader)模式;
    3.3 缓存容量、初始大小与并发级别设置;
    3.4 缓存移除与监听(invalidate + removalListener);
  4. 缓存回收策略:
    4.1 基于容量的回收(LRU);
    4.2 基于时间的回收(expireAfterWrite / expireAfterAccess);
    4.3 基于 JVM GC 的回收(weakKeys / weakValues / softValues);
    4.4 GC 回收引发的缓存颠簸问题与解决思路;
  5. 缓存算法简述:FIFO、LRU、LFU 三种常见策略;
  6. 用 LinkedHashMap 实现简易 LRU:
    6.1 LinkedHashMap 构造参数与访问顺序;
    6.2 覆盖 removeEldestEntry 实现容量控制;
    6.3 线程安全与功能局限性说明;
  7. 操作系统层面的预读与文件缓存:readahead 机制、完全加载策略;
  8. 缓存优化一般思路:何时用缓存、容量与命中率考量;
  9. 缓存的一些注意事项与示例:HTTP 304、CDN;

引言

在性能优化 - 案例篇:缓冲区中,介绍了“缓冲”这一优化手段——通过将数据暂存到内存缓冲区,批量顺序读写来缓解设备间的速度差异。与缓冲相伴随的“孪生兄弟”就是缓存(Cache)。缓存将常用数据放到相对高速的存储层(如内存)中,从而在后续访问时实现瞬时读取,显著提升性能。

举例而言:

  • 浏览热门页面时,只要缓存中已有渲染结果,就可以实现“秒开”;
  • 对数据库而言,引入缓存后,频繁查询热点记录可以直接命中缓存,数据库几乎无需负载。

缓存几乎是软件中最常见的优化技术。从 CPU L1/L2/L3 缓存到 Redis、Memcached 这样的分布式缓存,无不围绕“速度差异协调”这一核心展开。

接下来我们主要聚焦于进程内缓存——堆内缓存,以 Guava 的 LoadingCache 为示例讲解堆内缓存设计思路、常见回收策略和算法实现。


1. 缓存基本概念

缓存的核心作用,是在两个速度差异巨大的组件之间增加一层高速存储:

  • 速度慢组件:如数据库、文件存储,访问一次可能耗费几毫秒或更长;
  • 速度快组件:如 CPU 寄存器、内存读写,只需几十纳秒;
  • 缓存层(中间层):通常部署在内存中,通过哈希映射、LRU 回收等策略,只要缓存命中就能以几百纳秒返回结果。

根据缓存所在的物理位置,可将其分为:

  1. 进程内缓存(堆内缓存):直接存放在 JVM 堆里,访问速度最快,但容量受限于可用堆内存;
  2. 进程外缓存(进程间或分布式缓存):如 Redis、Memcached,通常运行在独立进程或集群里,通过网络访问,虽然速度比数据库快许多,但仍比堆内缓存慢一个数量级;

接下来重点讲解 进程内缓存,常见实现包括 Guava Cache、Caffeine、Ehcache、JCache 等。它们都提供了基于内存分片、高并发访问、灵活回收策略和统计监控的堆内缓存解决方案。

在这里插入图片描述


2. Guava 的 LoadingCache

在这里插入图片描述

Guava 提供了功能强大的 Cache 接口和 LoadingCache 实现,既支持手动存入(put()),也支持在缓存未命中时“自动加载”(CacheLoader)。下面通过示例逐步介绍其用法与内部配置要点。

2.1 引入依赖与初始化

首先,通过 Maven 将 Guava 库加入项目:

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>29.0-jre</version>
</dependency>

然后,使用 CacheBuilder 来创建一个 LoadingCache

LoadingCache<String, String> lc = CacheBuilder.newBuilder()// 设置最大缓存容量:达到上限后回收其他元素.maximumSize(1000)// 设置初始容量:底层 Hash 表的初始大小为 16(默认).initialCapacity(16)// 设置并发级别:将缓存分片成 4 个 segment,提升并发读写性能.concurrencyLevel(4).build(new CacheLoader<String, String>() {@Overridepublic String load(String key) throws Exception {// 缓存未命中时,自动调用 slowMethod 从外部数据源加载return slowMethod(key);}});
  • maximumSize(int):指定 缓存中可保留条目的最大数量,一旦超过,将根据回收策略(默认 LRU)移除旧元素;
  • initialCapacity(int):指定底层哈希表初始大小(bucket 数量),避免在缓存初始化时反复扩容;
  • concurrencyLevel(int):指定并发写的“分段”数,Guava 会将内部数据结构拆分为 concurrencyLevel 个部分,以减少并发冲突;

2.2 手动 put 与自动加载(CacheLoader)

LoadingCache 支持两种获取方式:

  1. 手动 put()

    lc.put("key1", "value1");
    String v = lc.getIfPresent("key1");  // 立即返回 "value1"
    

    在这种模式下,开发者负责将外部数据同步写入缓存。

  2. 自动加载 get()

在这里插入图片描述

// 第一次调用:缓存中无 key "a",触发 CacheLoader.load("a")
long start = System.nanoTime();
String result1 = lc.get("a");   // slowMethod("a") 需 1s
System.out.println("第一次调用耗时: " + (System.nanoTime() - start));
// 第二次调用:缓存命中,迅速返回
long start2 = System.nanoTime();
String result2 = lc.get("a");
System.out.println("第二次调用耗时: " + (System.nanoTime() - start2));

其中 load(String key) 方法可同步加载所需数据(如从数据库或外部 API 拉取),并在返回值后自动存入缓存。

2.2.1 示例代码

public class GuavaCacheDemo {// 模拟一个缓慢方法:睡眠 1 秒后返回结果static String slowMethod(String key) throws Exception {Thread.sleep(1000);return key + ".result";}public static void main(String[] args) throws Exception {LoadingCache<String, String> lc = CacheBuilder.newBuilder().maximumSize(1000).initialCapacity(16).concurrencyLevel(4).recordStats()   // 开启统计信息收集.build(new CacheLoader<String, String>() {@Overridepublic String load(String key) throws Exception {return slowMethod(key);}});// 第一次 get,会调用 slowMethodlong t1 = System.nanoTime();String v1 = lc.get("a");long elapsed1 = System.nanoTime() - t1;System.out.println("第一次 get 用时: " + elapsed1 + " ns");// 第二次 get,立即返回long t2 = System.nanoTime();String v2 = lc.get("a");long elapsed2 = System.nanoTime() - t2;System.out.println("第二次 get 用时: " + elapsed2 + " ns");// 输出命中率与加载次数等统计System.out.println("Cache Stats: " + lc.stats());}
}
  • recordStats():开启缓存统计功能,可用于后续分析 hitRate()loadSuccessCount() 等指标;
  • CacheLoader.load():当 key 未命中时,自动调用并将结果写回缓存;

2.3 缓存移除与监听(invalidate + removalListener)

  • 手动删除

    lc.invalidate("a");  // 移除 key "a" 对应的缓存项
    
  • 监听删除事件

    LoadingCache<String, String> lc2 = CacheBuilder.newBuilder().removalListener(notification -> {System.out.println("移除: " + notification.getKey() + " 因为 " + notification.getCause());}).maximumSize(100).build(new CacheLoader<>() {@Overridepublic String load(String key) { return slowMethod(key); }});
    

    当缓存项因为容量、过期、显式 invalidate() 等原因被移除时,监听器会收到回调,可用于日志、监控或二次清理。


3. 缓存回收策略

在缓存容量有限的前提下,需设计合适的回收策略来剔除“冷”或不再需要的数据,以保证“热点”数据得到优先保留。Guava 原生支持多种回收方式:

3.1 基于容量的回收(LRU)

  • maximumSize(long):当超过指定数量时,按照“最近最少使用(LRU)”策略移除最旧项;
  • LRU 意味着:每次缓存命中(get())或写入(put())时,该条目被标记为“最近被使用”;容量满时,优先移除最久未被访问的条目;
  • 这是默认的回收策略,适合大多数“热点覆盖度有限”的场景。

3.2 基于时间的回收

  • expireAfterWrite(long duration, TimeUnit unit):在缓存项被写入后,若在 duration 时间内未被访问,自动过期移除;
  • expireAfterAccess(long duration, TimeUnit unit):在缓存项最后一次访问后,若超过 duration,自动过期移除;
  • 这两种策略可以组合使用,用于场景如“用户会话缓存”、“短期热点数据”。

3.3 基于 JVM GC 的回收

  • Guava 提供了 weakKeys(), weakValues(), softValues() 等方法,利用不同强度的引用进行回收:

    • weakKeys():将缓存 key 按弱引用存放,若 key 对象仅被缓存引用,则可随时被 GC 回收,相应条目自动失效;
    • weakValues():将缓存 value 按弱引用存放,若 value 对象不再被强引用,则可被 GC 回收;
    • softValues():将 value 以软引用存放,当 JVM 内存不足时,GC 会优先回收这些软引用对象;
  • 典型语法:

    Cache<String, byte[]> cache = CacheBuilder.newBuilder().maximumSize(1000).weakValues().build();
    
  • 面试高频:若同时设置 weakKeys()weakValues(),则当 key 或 value 都失去任何强引用后,该条目会被 GC 回收。

3.3.1 GC 回收引发的缓存颠簸问题

当缓存条目使用弱引用或软引用,一旦 JVM 触发 GC,就可能一次性清空大批缓存数据。若该缓存频繁被访问,缓存将被迅速重新加载,导致连续触发多次 GC 和缓存“哗啦啦回补”的现象——CPU 消耗骤增,却无法留住数据。

解决思路

  • 仅对内存占用较大的非热点对象使用 softValues(),而不是对所有缓存。一旦发现缓存颠簸,可考虑放宽 GC 压力或降低缓存容量;
  • 尽量使用基于容量+时间的回收,避免过度依赖 JVM GC;
  • 在缓存加载逻辑中加入适当延迟,防止短时间内同一批 key 被重复加载。

4. 常见缓存算法简介

在这里插入图片描述

除了 Guava 提供的默认 LRU,缓存领域常见还有两种算法:

4.1 FIFO(先进先出)

  • 按“插入顺序”回收:

    • 缓存满时,移除最早插入的条目;
    • 结构简单,但不考虑条目热度;
    • 适用于“日志队列”、“任务处理队列”这类只关心先来先服务的场景。

4.2 LRU(最近最少使用)

  • 按“访问顺序”回收:

    • 每次 get()put() 时,将条目移至最近位置;
    • 满载时移除最久未被访问的条目;
    • 适用于“热点数据需长时间保留”的场景,是一般缓存中最为常见的策略。

4.3 LFU(最近最不常用)

  • 按“访问频率”回收:

    • 维护每个条目的访问计数;
    • 缓存满时,移除访问计数最少的条目;若存在多项访问计数相同,则移除“最久未使用”者;
    • 适用于需要保留“高访问频次”数据的场景,但实现较复杂,需要额外维护计数与优先级队列。

5. 简易 LRU 实现——LinkedHashMap

在 Java 中,要实现一个轻量级的 LRU 缓存,最便捷的方式是利用 LinkedHashMap 提供的“访问顺序”功能:

public class LRUCache<K, V> extends LinkedHashMap<K, V> {private final int capacity;public LRUCache(int capacity) {// 初始容量 16,负载因子 0.75,accessOrder=true 表示按访问顺序排列super(16, 0.75f, true);this.capacity = capacity;}// 当 put 后,自动调用此方法判断是否需要移除最老条目@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {return size() > capacity;}
}
  • 构造参数说明

    • initialCapacity:初始哈希表桶数,默认 16;
    • loadFactor:负载因子(0.75f);
    • accessOrder=true:按照“访问顺序”保持双向链表;
  • removeEldestEntry:在每次 put() 后自动调用,若返回 true,则移除“最久未访问”者,即 LRU 算法的核心。

在这里插入图片描述

5.1 功能局限与线程安全

  • 优势:代码简洁,无需自行维护优先级队列或计数器;

  • 局限

    1. 仅基于“条目数量”控制容量,不能指定基于“内存占用大小”回收;
    2. 无法设置“基于时间过期”或“基于访问次数”回收;
  • 线程安全LinkedHashMap 本身并非线程安全,如需并发访问,应加锁或改用 ConcurrentLinkedHashMap / Guava Cache / Caffeine。


6. 操作系统层面的预读与文件缓存

在这里插入图片描述

在操作系统层面,对文件 I/O 缓存设计也非常智能,进一步支撑了高性能缓存架构。Linux 下可以通过 free 命令查看内存状态,其中 cached 区域往往十分庞大:

$ free -htotal        used        free      shared  buff/cache   available
Mem:           16Gi       4.2Gi       2.5Gi       128Mi       9.4Gi       11Gi
Swap:         2.0Gi       512Mi       1.5Gi
  • buff/cache:表示操作系统将磁盘块缓存在内存中的容量,包括文件系统页缓存、目录缓存等;
  • Readahead(预读):当进程顺序读取文件时,内核会自动尝试以“页面”为单位预读后续若干页面,以减少随机读时的磁盘寻道开销。
    在这里插入图片描述

例如,若应用以 4KB 为单位读取大型文件,内核可能在后台提前载入 128KB 或更多连续页面,由此实现“顺序读取性能≈内存读取性能”的效果。

  • 完全加载策略:若某一小文件(如几 MB)访问频率极高,可在应用启动时一次将整个文件 mmap()read() 到内存(posix_fadvise(..., POSIX_FADV_WILLNEED)),确保后续访问都命中内核缓存;

7. 缓存优化的一般思路

在实际项目中,引入进程内缓存时,可根据以下几个准则:

  1. 缓存目标场景

    • 存在稳定的数据热点(某些 key 会被反复访问);
    • 读操作远多于写操作;
    • 下游服务(数据库、远程接口)性能低,成为瓶颈;
    • 缓存一致性要求相对宽松,偶尔允许短暂的“陈旧”数据。
  2. 缓存大小与容量

    • 缓存容量过小,会导致“热点”数据被频繁淘汰,命中率低,性能提升有限;
    • 缓存容量过大,会占用大量堆空间,增加 GC 频率与时长;
    • 通常通过监控缓存命中率(cache.stats().hitRate())来调整容量,推荐至少达到 50% 的命中率,若低于 10% 就要重新评估是否需要缓存。

在这里插入图片描述

  1. 回收策略选择

    • 默认使用 LRU,即 maximumSize(...)
    • 对于需要“短期热点”或“超时失效”的数据,可结合 expireAfterWrite(...)expireAfterAccess(...)
    • 若缓存数据对象非常大,且不想占用堆内存,可考虑 weakValues()softValues(),但要避免“缓存颠簸”现象。
  2. 监控与统计

    • 开启 recordStats(),收集命中、加载、移除次数等数据;
    • 定期导出或打印 cache.stats(),分析缓存命中率(hitRate)与平均加载时间(averageLoadPenalty);
    • 若发现加载成本过高,可考虑加大缓存容量或优化加载算法;
  3. 缓存失效与一致性

    • 当缓存中数据与源数据库数据不一致时,需要设计缓存更新/清理策略(如主动失效、定时刷新或消息通知触发刷新);
    • 对于对一致性要求极高场景,可使用“双写+事务+消息队列+双删失效”等方案,见后续“缓存一致性”课时。
  4. 预加载 vs 惰性加载

    • 惰性加载(Lazy Loading):在第一次访问时加载到缓存,常见于 LoadingCache
    • 预加载(Preloading):在应用启动时或定时调度时一次性加载所有热点数据,减少首次访问延迟;
    • 若热点集合较小且可预见,可采用预加载;若热点动态且数据量大,优先使用惰性加载。

8. 缓存应用案例

  1. HTTP 304(Not Modified)缓存

    • 浏览器发送条件性请求:带上 If-Modified-SinceETag
    • 服务端判断资源是否自上次修改以来未发生变化,若无改动则直接返回 304,让浏览器使用本地缓存;否则返回 200 并携带新的资源与缓存头;
    • 这样可以在浏览器端节省一次完整的资源下载,并允许操作系统与浏览器在内存/硬盘层面做更深层次的缓存。
  2. CDN(内容分发网络)缓存

    • 用户访问某个静态资源时,会首先到就近的 CDN 节点请求;
    • 若该节点已有缓存,直接返回给用户;否则节点会向**源站(Origin)**拉取一份并缓存在本地;
    • CDN 缓存策略包括 TTL(Time-To-Live)、LRU 或 LFU,来自不同运营商或网络环境下的缓存命中率优化直接影响用户体验与带宽成本。
  3. 数据库二级缓存

    • ORM 框架(如 Hibernate)常集成二级缓存,将热点实体缓存在本地 heap 或分布式缓存中;
    • 在事务提交或数据更新时,需要将对应缓存项失效或更新;
    • 缓存失效策略与事务边界息息相关,需要设计清晰的缓存注解或 AOP 拦截器。

9. 小结

进程内缓存(堆内缓存) 的设计思路与常见实现:

  1. 缓存本质与应用场景

    • 缓存用于调和下游“慢”与上游“快”之间的速度差异;
    • 典型场景包括:热点数据查询、配置读取、会话管理、短期临时数据。
  2. Guava LoadingCache

    • CacheBuilder 提供灵活配置:maximumSizeinitialCapacityconcurrencyLevel
    • 支持手动 put() 与自动加载(CacheLoader)两种模式;
    • 可通过 invalidate() 手动移除,并通过 removalListener 监听删除事件;
    • 回收策略包括基于容量(LRU)、基于时间(expireAfterWrite/Access)与 JVM 引用回收(weakKeys/weakValues/softValues);
    • 避免“软引用缓存颠簸”带来的频繁 GC 问题。
  3. 常见缓存算法

    • FIFO:先进先出,简单但不考虑热点;
    • LRU:最近最少使用,当前最流行,保留热点;
    • LFU:最近最不常用,保留高频访问数据,支持频次计数;
  4. 简易 LRU 实现

    • 利用 LinkedHashMap 构造参数 accessOrder=true,覆写 removeEldestEntry
    • 整体逻辑简单,但不支持过期时间与并发安全,需要在生产环境中慎用或加锁。
  5. 操作系统缓存与预读

    • Linux 内核会自动执行 readahead,预读后续页面到 cached 区域;
    • 可手动使用 mmap()posix_fadvise() 等方式实现“完全加载”,适用于小文件的高频访问。
  6. 缓存优化一般思路

    • 在缓存容量、命中率与 JVM GC 之间做折中;
    • CDC(缓存、数据库、集群)技术栈常见组合;
    • 监控 cache.stats() 指标,命中率需 ≥ 50% 才有较好收益;若 < 10% 则应卸载或重构缓存策略。
  7. 示例应用

    • HTTP 304、CDN 缓存;
    • 数据库二级缓存;
    • Redis 作为分布式缓存,面向更大规模数据。

在这里插入图片描述

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

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

相关文章

使用jstack排查CPU飙升的问题记录

最近&#xff0c;看到短视频传播了一个使用jstack来协助排查CPU飙升的案例。我也是比较感兴趣&#xff0c;参考了视频博主的流程&#xff0c;自己做了下对应案例的实战演练&#xff0c;在此&#xff0c;想做一下&#xff0c;针对相关问题模拟与排查演练的实战过程记录。 案例中…

Sql Server 中常用语句

1.创建用户数据库 --创建数据库 use master --切换到master数据库 go-- 终止所有与SaleManagerDB数据库的连接 alter database SaleManagerDB set single_user with rollback immediate goif exists (select * from sysdatabases where nameSaleManagerDB) drop database Sal…

联通专线赋能,亿林网络裸金属服务器:中小企业 IT 架构升级优选方案

在当今数字化飞速发展的时代&#xff0c;中小企业面临着日益增长的业务需求与复杂多变的市场竞争环境。如何构建高效、稳定且具性价比的 IT 架构&#xff0c;成为众多企业突破发展瓶颈的关键所在。而亿林网络推出的 24 核 32G 裸金属服务器&#xff0c;搭配联通专线的千兆共享带…

LangChain核心之Runnable接口底层实现

导读&#xff1a;作为LangChain框架的核心抽象层&#xff0c;Runnable接口正在重新定义AI应用开发的标准模式。这一统一接口设计将模型调用、数据处理和API集成等功能封装为可复用的逻辑单元&#xff0c;通过简洁的管道符语法实现复杂任务的声明式编排。 对于面临AI应用架构选择…

CSP严格模式返回不存在的爬虫相关文件

文章目录 说明示例&#xff08;返回404&#xff09;示例&#xff08;创建CSP例外&#xff09; 说明 日期&#xff1a;2025年6月4日。 CSP严格模式是default-src none&#xff0c;但有些web应用中&#xff0c;在爬虫相关文件不存在的情况下&#xff0c;依旧返回了对应文件&…

DeviceNET从站转EtherNET/IP主站在盐化工行业的创新应用

在工业自动化飞速发展的今天&#xff0c;盐化工行业也在积极探索智能化升级的路径。其中&#xff0c;设备之间的高效通信与协同工作成为了提升生产效率和质量的关键。而JH-DVN-EIP疆鸿智能DeviceNET从站转EtherNET/IP主站的技术应用&#xff0c;为盐化工行业带来了全新的解决方…

安装 Nginx

个人博客地址&#xff1a;安装 Nginx | 一张假钞的真实世界 对于 Linux 平台&#xff0c;Nginx 安装包 可以从 nginx.org 下载。 Ubuntu: 版本Codename支持平台12.04precisex86_64, i38614.04trustyx86_64, i386, aarch64/arm6415.10wilyx86_64, i386 在 Debian/Ubuntu 系统…

默认网关 -- 负责转发数据包到其他网络的设备(通常是路由器)

✅ 默认网关概括说明&#xff1a; 默认网关&#xff08;Default Gateway&#xff09;是网络中一台负责转发数据包到其他网络的设备&#xff08;通常是路由器&#xff09;。当一台主机要访问不在本地子网内的设备时&#xff0c;会将数据包发给默认网关&#xff0c;由它继续转发…

cv::FileStorage用法

cv::FileStorage 是 OpenCV 中的一个类&#xff0c;用于读取和写入结构化数据&#xff08;如 YAML、XML、JSON&#xff09;。它非常适合保存和加载诸如&#xff1a; 相机内参&#xff08;K、D&#xff09; 位姿&#xff08;R、T&#xff09; IMU 数据 配置参数 向量、矩阵、…

WebFuture:启动服务提示Job webfuture.service/start failed with result ‘dependency‘处理办法

问题分析&#xff1a; 当出现 Job webfuture.service/start failed with result dependency. 这样的错误提示时&#xff0c;通常意味着 webfuture.service 这个服务在启动时因为依赖关系的问题而未能成功启动 解决办法&#xff1a; 原因分析&#xff1a; webfuture.service 可…

Java 大视界 -- Java 大数据机器学习模型在遥感图像变化检测中的应用与改进(235)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也期待你毫无保留地分享独特见解,愿我们于此携手成长,共赴新程!💖 全网…

HarmonyOS运动开发:精准估算室内运动的距离、速度与步幅

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在室内运动场景中&#xff0c;由于缺乏 GPS 信号&#xff0c;传统的基于卫星定位的运动数据追踪方法无法使用。因此&#xff0c;如何准确估算室内运动的距离、速度和步幅&#xff0c;…

商品模块中的多规格设计:实现方式与电商/ERP系统的架构对比

在商品管理系统中&#xff0c;多规格设计&#xff08;Multi-Specification Product Design&#xff09;是一个至关重要但又极具挑战性的领域。无论是面向消费者的电商系统&#xff0c;还是面向企业管理的ERP系统&#xff0c;对商品规格的处理方式直接影响库存管理、订单履约、数…

HTML 等价字符引用:系统化记忆指南

HTML 等价字符引用:系统化记忆指南 在 HTML 中,字符引用(Character Entity References)用于表示保留字符或特殊符号。我将提供一个系统化的方法来记忆这些重要实体,并解释它们的实际应用。 什么是等价字符引用? HTML 字符引用有两种形式: 命名实体:&entity_name…

Java 线程池原理详解

Java 线程池原理详解 一、引言 在高并发场景下&#xff0c;频繁地创建与销毁线程将带来极大的性能开销。为了提升资源复用性与程序响应速度&#xff0c;Java 提供了线程池机制&#xff08;java.util.concurrent 包&#xff09;。线程池通过复用线程、控制线程数量、任务排队管…

Mybatis入门到精通

一&#xff1a;什么是Mybatis 二&#xff1a;Mybatis就是简化jdbc代码的 三&#xff1a;Mybatis的操作步骤 1&#xff1a;在数据库中创建一个表&#xff0c;并添加数据 我们这里就省略了 2&#xff1a;Mybatis通过maven来导入坐标&#xff08;jar包&#xff09; 3&#xff1a…

化学方程式配平免费API接口教程

接口简介&#xff1a; 根据反应物和生成物配平化学方程式。 请求地址&#xff1a; https://cn.apihz.cn/api/other/hxfcs.php 请求方式&#xff1a; POST或GET。 请求参数&#xff1a; 【名称】【参数】【必填】【说明】 【用户ID】【id】【是】【用户中心的数字ID&#xff…

Spring学习笔记:Spring的基于注解的XML的详细配置

按照刘Java的顺序&#xff0c;应该是从基于XML的DI开始接着上面的关于IoC容器装配。主要介绍学习Spring的XML基于注解的详细配置。 第一步是搭建一个Spring的基础工程&#xff08;maven管理&#xff09;&#xff0c;通过IoC机制获取IoC容器的对象。 创建maven工程并在pom文件…

(四)动手实现多层感知机:深度学习中的非线性建模实战

1 多层感知机&#xff08;MLP&#xff09; 多层感知机&#xff08;Multilayer Perceptron, MLP&#xff09;是一种前馈神经网络&#xff0c;包含一个或多个隐藏层。它能够学习数据中的非线性关系&#xff0c;广泛应用于分类和回归任务。MLP的每个神经元对输入信号进行加权求和…

第十三篇:MySQL 运维自动化与可观测性建设实践指南

本篇重点介绍 MySQL 运维自动化的关键工具与流程&#xff0c;深入实践如何构建高效可观测体系&#xff0c;实现数据库系统的持续稳定运行与故障快速响应。 一、为什么需要 MySQL 运维自动化与可观测性&#xff1f; 运维挑战&#xff1a; 手动备份容易遗漏或失败&#xff1b; …