《后端程序猿 · Caffeine 本地缓存》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 CSDN入驻一周,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,如需交流,欢迎留言评论。👍

文章目录

    • 写在前面的话
    • 技术统括
      • 技术简介
      • 选型比较
    • 实战运用
      • 快速入门
      • Bean和Util
      • SpringCache 模式
    • 技术拓展
      • 配置属性
      • 清除/驱逐策略
      • 过期/更新策略
      • 填充策略
      • 移除监听
      • 写入/删除监听
      • 统计信息
    • 总结陈词

写在前面的话

笔者所在公司的框架采用 Redis 作为缓存中间件,在部分场景下,可以借用 Redis 实现增强接口性能、减轻数据库压力、充当持久存储等功能。 但程序访问 Redis 毕竟需要消耗网络带宽,此外,经常由于各种因素导致 Redis 的性能降低,诸如编码不当、键过多、 网络异常等。 鉴于此,公司框架基于 Google 开发的高性能的 Java 缓存库 Caffeine,封装了本地缓存工具,便于业务项目使用。由于目前 Redis 已广泛使用,框架层面并未将本地缓存与 @Cacheable 等注解绑定,而是基于按需使用的原则,以注入 Bean 的形式封装工具方法


技术统括

技术简介

【Caffeine 技术简介】
Caffeine 是一个高性能的 Java 本地缓存库,提供了强大的缓存功能和灵活的配置选项,你可以使用 Caffeine 来实现本地缓存,并根据具体的需求进行配置和使用。
Caffeine 是基于 Java8 的高性能本地缓存库,并且在 Spring5 (SpringBoot 2.x) 后,Spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件。
Caffeine 是在 Guava Cache 的基础上做一层封装,性能有明显提高,二者同属于内存级本地缓存,从并发的角度来讲,Caffeine明显优于Guava,原因是使用了Java 8最新的StampedLock锁技术。

据说,比 Guava Cache 优秀,那既然 Guava 还没开始用,那就直接它吧。
Maven依赖都不需要单独引入,SB2.x自动引入了,爽。

【Caffeine 优势特性】
Caffeine提供灵活的结构来创建缓存,并且有以下特性:
自动加载条目到缓存中,可选异步方式
可以基于大小剔除
可以设置过期时间,时间可以从上次访问或上次写入开始计算
异步刷新
keys自动包装在弱引用中
values自动包装在弱引用或软引用中
条目剔除通知
缓存访问统计

【Caffeine 使用场景】
Caffeine 是一个高性能的 Java 本地缓存库,适用于各种日常开发场景。
以下是一些 Caffeine 在日常开发中适合做的事情:
缓存常用数据:使用 Caffeine 缓存常用的数据,例如配置信息、用户信息、系统参数等,可以提高数据的访问速度和系统的性能。
减轻数据库压力:将频繁访问的数据库查询结果缓存到 Caffeine 中,可以减轻数据库的压力,提高系统的并发处理能力。
缓存计算结果:使用 Caffeine 缓存计算结果,例如复杂查询结果、数据聚合结果等,可以避免重复计算,提高系统的响应速度。
实现数据预热:在系统启动时将一些常用的数据预先加载到 Caffeine 缓存中,可以提高系统的初始化速度和响应速度。
实现请求限流:使用 Caffeine 缓存来记录请求次数和频率,实现请求的限流和流量控制,保护系统的稳定性和可用性。
实现本地锁:利用 Caffeine 缓存的原子性操作特性,可以实现分布式锁的简单版本,用于控制并发访问。
缓存控制器结果:在 Spring MVC 或 Spring Boot 应用中,可以使用 Caffeine 缓存控制器方法的返回结果,减少方法的执行次数,提高系统的性能和吞吐量。
总的来说,Caffeine 是一个功能强大、性能优越的本地缓存库,适用于各种日常开发场景,可以提高系统的性能、稳定性和可维护性。

【 补充:Guava LoadingCache 适合存储那些满足以下条件的数据】
频繁访问的数据:LoadingCache 提供了高性能的数据读取和写入,适合缓存那些被频繁访问的数据。这些数据可能是热点数据,经常被应用程序读取,但不经常更新。
计算密集型或者昂贵的数据:LoadingCache 可以在缓存中存储一些计算密集型或者昂贵的数据,例如数据库查询结果、API 调用结果等。这样可以避免重复计算或者昂贵的网络请求,提高系统的性能和响应速度。
临时性的数据:LoadingCache 也适合存储一些临时性的数据,例如会话数据、用户权限信息等。这些数据可能在一段时间内频繁被访问,但是不需要长期保存。
不需要持久化的数据:LoadingCache 是一个本地缓存,不具备持久化存储的能力。因此适合存储一些不需要长期保存的数据,例如缓存数据源的数据、临时计算结果等。
需要自动加载和刷新的数据:LoadingCache 支持自动加载和刷新数据,可以通过设置 refreshAfterWrite 来定期刷新缓存数据,以保持数据的新鲜性。因此适合存储那些需要定期刷新的数据,例如缓存数据源的数据、动态配置信息等。
总的来说,LoadingCache 适合存储那些被频繁访问、不需要持久化存储、临时性的数据,以及那些需要自动加载和刷新的数据。通过合理使用 LoadingCache,可以提高系统的性能、减少资源消耗,同时提供更好的用户体验。


选型比较

【Caffeine 和 GuavaCache 差异】
剔除算法方面,GuavaCache采用的是「LRU」算法,而Caffeine采用的是「Window TinyLFU」算法,这是两者之间最大,也是根本的区别。
立即失效方面,Guava会把立即失效 (例如:expireAfterAccess(0) and expireAfterWrite(0)) 转成设置最大Size为0。这就会导致剔除提醒的原因是SIZE而不是EXPIRED。Caffiene能正确识别这种剔除原因。
取代提醒方面,Guava只要数据被替换,不管什么原因,都会触发剔除监听器。而Caffiene在取代值和先前值的引用完全一样时不会触发监听器。
异步化方方面,Caffiene的很多工作都是交给线程池去做的(默认:ForkJoinPool.commonPool()),例如:剔除监听器,刷新机制,维护工作等。

【Caffeine 和 Redis 区别】
本地缓存与分布式缓存对应,缓存进程和应用进程同属于一个JVM,数据的读、写在一个进程内完成。本地缓存没有网络开销,访问速度很快。
从横向对常用的缓存进行对比,有助于加深对缓存的理解,有助于提高技术选型的合理性。下面对比三种常用缓存:Redis、EhCache、Caffeine。
image.png

通常采用 Caffeine/Guava + Redis 实现二级缓存方案,先从本地拿,拿不到再从缓存获取,减少 Redis 的连接消耗。

【Caffeine 有什么用,为什么不直接用Map】
**解答1:**Caffeine 使用了 ConcurrentHashMap 作为其缓存数据结构的基础,但对其进行了一些优化和改进,以提高并发性能、减少内存消耗,并添加了一些额外的功能和特性,使其更适合于高性能的缓存应用场景。
ConcurrentHashMap 是 Java 标准库中提供的线程安全的哈希表实现,它使用了一种分段锁的方式来实现并发访问控制,以提高并发读写性能。Caffeine 利用了 ConcurrentHashMap 的并发性能和线程安全性,并在此基础上进行了优化和改进,以提供更高性能的缓存服务。
总的来说,尽管 Caffeine 的底层实现基于 ConcurrentHashMap,但它对 ConcurrentHashMap 进行了一些改进和扩展,使得它更适合于高性能、低延迟的缓存应用场景。
**解答2:**Caffeine 是一个用于构建内存缓存的 Java 库,它提供了一些高效、可配置的缓存功能,可以帮助开发人员在应用程序中轻松地实现缓存机制。
与直接使用 Java 中的 Map 不同,Caffeine 提供了更多的特性和优势,使得它在某些场景下更为适用:
自动加载和刷新机制:Caffeine 支持自动加载和刷新缓存中的条目,无需手动编写加载逻辑。通过 LoadingCache 接口,可以在缓存中不存在指定键的条目时,自动调用加载逻辑来获取新的值,并将其放入缓存中。
缓存的自动清理和过期处理:Caffeine 提供了可配置的过期策略,可以根据时间、大小或其他条件来自动清理缓存中的条目。这样可以确保缓存不会占用过多的内存,并及时清理过期的条目,保持缓存的有效性和性能。
高性能和低内存占用:Caffeine 的实现经过优化,具有很高的性能和低的内存占用。它使用了一些高效的数据结构和算法,以及基于并发的设计模式,可以在多线程环境下高效地处理并发访问和更新操作。
可扩展性和灵活性:Caffeine 提供了丰富的配置选项和扩展点,可以根据具体的需求和场景来定制缓存的行为。开发人员可以灵活地配置缓存的大小、过期时间、刷新策略等参数,以满足不同应用场景的需求。
总的来说,尽管 Java 中的 Map 提供了基本的键值对存储功能,但在需要更多高级特性和性能优化的场景下,使用 Caffeine 可能会更加合适和方便。Caffeine 提供了更丰富的功能和更高效的实现,可以帮助开发人员构建出更可靠、更高性能的缓存系统。


实战运用

快速入门

Step1、添加Maven依赖

注意,高版本Spring或SB以及依赖了caffeine,直接使用提供的版本即可,不要再额外引入了。

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.8</version>
</dependency>

Step2、编写工具Bean

@Component
public class CaffeineCache {

    private final Cache<String, Object> cache;

    public CaffeineCache() {
        // 创建一个基于 Caffeine 的本地缓存,设置最大缓存条目数为 10000,过期时间为 10 分钟
        cache = Caffeine.newBuilder()
                .maximumSize(10000)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build();
    }

    // 添加缓存项
    public void put(String key, Object value) {
        cache.put(key, value);
    }

    // 获取缓存项
    public Object get(String key) {
        return cache.getIfPresent(key);
    }

    // 移除缓存项
    public void remove(String key) {
        cache.invalidate(key);
    }

    // 清空缓存
    public void clear() {
        cache.invalidateAll();
    }
}

Step3、使用测试

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Autowired
    private CaffeineCache caffeineCache;

    public void doSomething() {
        // 添加缓存项
        caffeineCache.put("key", "value");

        // 获取缓存项
        Object value = caffeineCache.get("key");

        // 移除缓存项
        caffeineCache.remove("key");

        // 清空缓存
        caffeineCache.clear();
    }
}

通过以上步骤,你就可以在 Spring Boot 应用中使用 Caffeine 工具类来创建本地缓存,并在需要时进行缓存操作。你可以根据具体的需求调整缓存的配置参数,例如最大缓存条目数、过期时间等。

Bean和Util

将 Caffeine 缓存工具类设计为 Bean 是比较常见的做法,这样可以更好地与 Spring Boot 集成,并通过依赖注入的方式在需要的地方直接使用,同时也方便在配置类中对其进行配置和管理。
将 Caffeine 缓存工具类设计为 Bean 的优势包括:
便于管理和配置:作为 Spring Bean,可以利用 Spring 的依赖注入和配置功能,更方便地管理和配置 Caffeine 缓存的属性,如最大缓存条目数、过期时间等。
与 Spring Boot 集成更紧密:作为 Spring Bean,与 Spring Boot 的集成更加紧密,可以直接在其他 Bean 中通过自动装配进行使用,而不需要额外的配置。
易于测试:将 Caffeine 缓存工具类设计为 Bean 后,可以更方便地在单元测试中进行模拟和替换,提高测试的可维护性和灵活性。
因此,建议将 Caffeine 缓存工具类设计为 Spring Bean,以便更好地利用 Spring Boot 的特性和功能,并方便在应用程序中使用和管理。


SpringCache 模式

与SB整合通常体现在@Cacheable,有需要再扩展。
公司框架Redis使用已久,为减少影响,还是封装工具Bean,按需使用。


技术拓展

配置属性

initialCapacity 初始的缓存空间大小
maximumSize 缓存的最大条数
maximumWeight 缓存的最大权重
expireAfterAccess 最后一次写入或访问后,经过固定时间过期
expireAfterWrite 最后一次写入后,经过固定时间过期
refreshAfterWrite 写入后,经过固定时间过期,下次访问返回旧值并触发刷新
weakKeys 打开 key 的弱引用
weakValues 打开 value 的弱引用
softValues 打开 value 的软引用
recordStats 缓存使用统计
expireAfterWrite 和 expireAfterAccess 同时存在时,以 expireAfterWrite 为准。
weakValues 和 softValues 不可以同时使用。
maximumSize 和 maximumWeight 不可以同时使用。

清除/驱逐策略

缓存的驱逐策略是为了预测哪些数据在短期内最可能被再次用到,从而提升缓存的命中率。LRU策略或许是最流行的驱逐策略。但LRU通过历史数据来预测未来是局限的,它会认为最后到来的数据是最可能被再次访问的,从而给予它最高的优先级。
Caffeine提供三类驱逐策略:基于大小(size-based),基于时间(time-based)和基于引用(reference-based)

1、基于大小(size-based)
基于大小驱逐,有两种方式:一种是基于缓存大小,一种是基于权重。

// 根据缓存的计数进行驱逐
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
    .maximumSize(10_000)
    .build(key -> createExpensiveGraph(key));

// 根据缓存的权重来进行驱逐(权重只是用于确定缓存大小,不会用于决定该缓存是否被驱逐)
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
    .maximumWeight(10_000)
    .weigher((Key key, Graph graph) -> graph.vertices().size())
    .build(key -> createExpensiveGraph(key));

2、基于时间:设置缓存的有效时间

// 设置缓存有效期为 10 秒,从最后一次写入开始计时 
Cache<String, String> cache = Caffeine.newBuilder()
    .expireAfterWrite(Duration.ofSeconds(10)) 
    .build();

3、基于引用:设置缓存为软引用或弱引用,利用GC来回收缓存数据。

// 性能较差,不建议使用。
Cache<String, String> cache = Caffeine.newBuilder()
        .weakKeys().weakValues().build();

【弱引用相关补充】

Caffeine.weakKeys() 使用弱引用存储key。如果没有强引用这个key,则GC时允许回收该条目
Caffeine.weakValues() 使用弱引用存储value。如果没有强引用这个value,则GC时允许回收该条目
Caffeine.softValues() 使用软引用存储value, 如果没有强引用这个value,则GC内存不足时允许回收该条目

image.png


过期/更新策略

# expireAfterAccess:设置条目在最后一次访问后的过期时间。默认值为不过期。
# expireAfterWrite:设置条目在被创建或最后一次写入后的过期时间。默认值为不过期。
# refreshAfterWrite:这个其实算更新策略,设置条目在被创建或最后一次写入后的自动刷新时间。默认值为不自动刷新。
# expireAfter:
# 在expireAfter中需要自己实现Expiry接口,这个接口支持create,update,access了之后多久过期,
# 这里和前面两个API不同的是,需要你告诉缓存框架,他应该在具体的某个时间过期
# 也就是通过前面的重写create,update,access的方法,获取具体的过期时间。
Cache<String, String> cacheHandle = Caffeine.newBuilder()
        .expireAfter(new Expiry<String, String>() {
            // 创建后多久过期
            @Override
            public long expireAfterCreate(@NonNull String key, @NonNull String value, long currentTime) {
                return TimeUnit.SECONDS.toNanos(3); //3秒后过期
            }
            // 更新后多久过期
            @Override
            public long expireAfterUpdate(@NonNull String key, @NonNull String value, long currentTime, @NonNegative long currentDuration) {
                return currentDuration; // 保持不变,即不改变过期时间
            }
            // 读取后多久过期
            @Override
            public long expireAfterRead(@NonNull String key, @NonNull String value, long currentTime, @NonNegative long currentDuration) {
                return currentDuration; // 保持不变,即不改变过期时间
            }
        })
        .build();
cacheHandle.put("abc", "123");
System.out.println("abc的值:" + cacheHandle.getIfPresent("abc"));
ThreadUtil.sleep(5000);
System.out.println("abc的值:" + cacheHandle.getIfPresent("abc"));

填充策略

Caffeine 提供了四种缓存添加策略:手动加载,自动加载,手动异步加载和自动异步加载。
很好理解,其实就是build的几个重载模式。
参考:Caffeine Cache 进程缓存利器


移除监听

RemovalListener:如果我们需要在缓存被移除的时候,得到通知产生回调,并做一些额外处理工作。

Cache<String, String> cache = Caffeine.newBuilder()
        .maximumSize(2)
        .removalListener(((key, value, cause) -> {
            System.out.println("Removed key: " + key + ", value: " + value + ", cause: " + cause);
        }))
        .build();
cache.put("key1", "value1");
cache.put("key2", "value22");
cache.put("key3", "value333");
ThreadUtil.sleep(1000);
System.out.println(cache.asMap());

//下方是输出信息:
Removed key: key1, value: value1, cause: SIZE
{key2=value22, key3=value333}

写入/删除监听

@Autowired
private OnelinkCaffeineCacheHandle caffeineCache;

Caffeine<Object, Object> customBuild = caffeineCache.getCustomBuild();
customBuild.writer(new CacheWriter<String, String>() {
    @Override
    public void write(String key, String value) {
        System.out.println("Cache entry written for key: " + key + ", value: " + value);
    }
    @Override
    public void delete(String key, String value, RemovalCause cause) {
        System.out.println("Cache entry removed for key: " + key + ", value: " + value + ", removal cause: " + cause);
    }
});

统计信息

【关于 CacheStats】
Guava 的 CacheStats 类是用来表示缓存的统计信息的。它提供了一组方法来获取缓存的命中率、加载次数、加载失败次数等信息。通过这些统计信息,可以帮助你了解缓存的使用情况,优化缓存的配置和性能。
以下是 CacheStats 类的一些常用方法:
hitCount():返回缓存命中的次数。
missCount():返回缓存未命中的次数。
loadSuccessCount():返回缓存加载成功的次数。
loadExceptionCount():返回缓存加载失败的次数。
totalLoadTime():返回缓存加载的总时间,单位为纳秒。
evictionCount():返回缓存中条目被回收的次数。
使用 CacheStats 类可以帮助你监控缓存的性能,并且根据统计信息来调整缓存的配置,以提高系统的性能和稳定性。

【示例代码】

Tips:for循环中大量使用才有统计的意义,正常生产环境也没必要记录。

public static void main(String[] args) {
    Cache<String, String> cache = Caffeine.newBuilder()
            .maximumSize(2)
            .recordStats()
            .removalListener(((key, value, cause) -> {
                System.out.println("Removed key: " + key + ", value: " + value + ", cause: " + cause);
            }))
            .build();
    
    // 添加一些条目
    cache.put("key1", "value1");
    cache.put("key2", "value22");
    cache.put("key3", "value333");
    ThreadUtil.sleep(1000);
    
    // 此时缓存大小超过最大权重,将会驱逐一些条目
    System.out.println(cache.asMap());
    System.out.println(cache.stats());
    
    //输出信息如下:
    // Removed key: key1, value: value1, cause: SIZE
    // {key2=value22, key3=value333}
    // CacheStats{hitCount=0, missCount=0, loadSuccessCount=0, loadFailureCount=0, totalLoadTime=0, evictionCount=1, evictionWeight=1}
    // hitCount(): 返回命中缓存的总数
    // evictionCount():缓存逐出的数量
}

总结陈词

上文介绍了本地缓存的用法,仅供参考。
本地缓存具备其独有美丽,可以搭配Redis发挥更多作用。
但切记缓存都是一个双刃剑,用的姿势如果不对,会造成更严重的后果。

💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SolrCloud Autoscaling 自动添加副本

SolrCloud Autoscaling 自动添加副本 前言 问题描述 起因是这样的&#xff0c;我在本地调试 Solr 源码&#xff08;版本 7.7.3&#xff09;&#xff0c;用 IDEA 以 solrcloud 方式启动了 2 个 Solr 服务&#xff0c;如下所示&#xff1a; 上图的启动参数 VM Options 如下&am…

QT控制comboBox切换方法

目录 1. 效果2. 操作 1. 效果 如下图&#xff1a; 点击全切换雨天模式按钮 则 comboBox 文本显示为 “雨天模式”点击全切换正常模式按钮 则 comboBox 文本显示为 “雨天模式” 切换到 雨天模式 切换到 正常模式 2. 操作 使用 “setCurrentIndex” 方法&#xff0c;切换 combo…

vmware虚拟机增加磁盘容量

概述 当初始分配给虚拟机的磁盘空间不够时&#xff0c;需要从外部的主系统增加配给。 具体操作分为两步&#xff1a;一&#xff1a;通过虚拟机界面添加分配的磁盘配给&#xff1b;二&#xff1a;将新分配的配给给使用起来。 操作 添加磁盘配给 在虚拟机内部添加新分配的配给…

安装Intel Realsense D435i驱动与ROS包报错

1.下载安装realsense SDK 1.1 安装依赖 sudo apt install libudev-dev pkg-config libgtk-3-dev sudo apt install libusb-1.0-0-dev pkg-config sudo apt install libglfw3-dev sudo apt install libssl-dev1.2 权限 cd librealsense/ sudo cp config/99-realsense-libusb.…

独享代理VS共享代理,新手选择攻略

随着互联网的广泛普及和应用&#xff0c;涉及网络隐私、数据安全和网络访问控制的问题变得越来越重要。代理服务器作为一种常见的网络工具&#xff0c;可以在跨境电商、海外社媒、SEO投放、网页抓取等领域发挥作用&#xff0c;实现匿名访问并加强网络安全。在代理服务器类别中&…

GoLand 2024 for Mac GO语言集成开发工具环境

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff08;适合自己的M芯片版或Intel芯片版&#xff09;&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功3、打开访达&#xff0c;点击【文…

哪个牌子的充电宝牌子便宜好用?2024年性价比高充电宝排行榜!

在 2024 年&#xff0c;充电宝市场依旧琳琅满目&#xff0c;让人眼花缭乱。大家都在寻找那个既便宜又好用的充电宝&#xff0c;可面对众多品牌和产品&#xff0c;常常感到无从下手。别担心&#xff01;经过深入的市场调研和实际使用体验&#xff0c;我们为您精心整理出了 2024 …

掌握空投,预见未来:空投教程网,撸毛党的必备工具

随着区块链技术的发展&#xff0c;越来越多的人开始关注这一领域。对于很多人来说&#xff0c;如何有效地参与区块链项目&#xff0c;尤其是空投活动&#xff0c;成为了一个重要的问题。为了解决这一问题&#xff0c;“空投教程网”应运而生。作为一个专为撸毛党设计的工具&…

【高中数学/基本不等式】已知:x,y皆大于1,且x+2y=4 求:1/(x-1)+1/(y-1)的最小值为?

【问题来源】 https://www.ixigua.com/7025123539728466469?logTag1c2fd2e305d60e6277ab 之第一题 【问题】 已知&#xff1a;x,y皆大于1&#xff0c;且x2y4 求&#xff1a;1/(x-1)1/(y-1)的最小值为&#xff1f; 【解答】 解&#xff1a; 若将(x2y)/41代入目标式&…

【PostgreSQL】数据基石:PostgreSQL的数据类型与表结构设计

目录 核心数据类型深入探索 基础数值与文本类型 日期与时间类型 特殊与复合类型 JSON与HSTORE 表的创建、修改与管理 创建与修改表结构 索引与性能优化 约束与数据完整性 核心数据类型深入探索 PostgreSQL以其多样化的数据类型著称&#xff0c;不仅包括标准SQL数据类型…

昇思25天学习打卡营第04天 | 数据集 Dataset

昇思25天学习打卡营第04天 | 数据集 Dataset 文章目录 昇思25天学习打卡营第04天 | 数据集 Dataset数据集加载数据集迭代数据集的变换shufflemapbatch 自定义数据集可随机访问数据集对象可迭代数据集生成器 总结打卡 数据集Dataset对原始数据进行封装、变换&#xff0c;为神经网…

光照老化试验箱在化工产品暴晒测试中的应用

概述 光照老化试验箱是一种模拟自然光照条件下材料老化情况的实验设备&#xff0c;广泛应用于化工、建材、电子、汽车等行业中对材料的耐候性、耐光性能等进行测试。通过模拟日光中的紫外线和温度等环境因素&#xff0c;加速材料老化过程&#xff0c;以此评估材料在长期使用中…

C语言编程-基于单链表实现贪吃蛇游戏

基于单链表实现贪吃蛇游戏 1.定义结构体参数 蛇行走的方向 蛇行走的状态 蛇身节点类 维护蛇的结构体型 2.游戏运行前预备工作 定位光标位置 游戏欢迎界面 绘制游戏地图&#xff08;边界&#xff09; 初始化游戏中的蛇身 创建食物 3.游戏运行 下一个位置是食物&#xff0c;就吃掉…

阿里云 SAE 助力修正商城 3 周内提升系统承载能力 20 倍,轻松应对春晚流量

作者&#xff1a;赵世振、刘松伟、朱坪" 从了解阿里云 SAE 到使用 SAE 进行应用架构升级共经历 3 周&#xff0c;这 3 周我们系统能承载的 QPS 从 5000 增强到 10 万&#xff0c;提升 20 倍&#xff0c;轻松应对了春晚大促流量洪波。并且&#xff0c;SAE 还帮助我们降低了…

超详细:安装Linux系统、虚拟现实教程

文章目录 一、如何下载并使用VMware虚拟机1.百度搜索vmware2.进入官网点击Workstation Pro链接3.博通注册对应的账号4.博通填写用户名、密码后直接登录会跳转到博通登录页5.个人使用选择个人版 二、国内镜像网站下载&#xff08;Centos版本&#xff09;三、镜像系统的安装1.打开…

PCL小笔记

一、常用概念 1&#xff0c;过滤器Filters 消除噪音 2&#xff0c;特征Features 集合点属性&#xff1a;曲面的曲率估计和查询点的法线 通过k-neighborhood计算得到这两个属性作为特征 查找方法&#xff1a;KD-tress、八叉树等 3&#xff0c;关键点Keypoints 可以利用明确标…

Halcon支持向量机

一 支持向量机 1 支持向量机介绍&#xff1a; 支持向量机(Support Vector Machine&#xff0c;SVM)是Corinna Cortes和Vapnik于1995年首先提出的&#xff0c;它在解决小样本、非线性及高维模式识别表现出许多特有的优势。 2 支持向量机原理: 在n维空间中找到一个分类超平面…

4.整合第三方技术【整合JUnit】

目录 1.创建项目&#xff1a; 2.导入测试对应的starter 3.添加测试对象 3.1 添加Prodcut接口文件 3.2 添加ProdcutImpl文件 3.3 测试类添加测试文件&#xff0c;并开始测试 4.测试类文件解析 4.1.测试类使用SpringBootTest修饰 4.2使用自动装配的形式添加要测试的对象 1.…

LeetCode 算法:路径总和 III c++

原题链接&#x1f517;&#xff1a;路径总和 III 难度&#xff1a;中等⭐️⭐️ 题目 给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶…

大模型与机器人精彩碰撞-7月5日晚上八点不见不散!

在瞬息万变的科技时代&#xff0c;新兴人工智能和机器人技术的结合正在引领新一轮的创新浪潮。你是否想成为未来科技的领航者&#xff1f;你是否想了解最前沿的AI与机器人技术&#xff1f;行麦科技重磅推出的“AIGC时代的生存法则”AI系列课&#xff0c;将为你揭开大模型与机器…