欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 實現(xiàn)緩存的三種方式及問題匯總

 更新時間:2024年03月29日 10:07:07   作者:楓飄長安  
這篇文章主要介紹了Java 實現(xiàn)緩存的三種方式及問題匯總,HashMap實現(xiàn)緩存,可以實現(xiàn)簡單的本地緩存,但是實際開發(fā)中不推薦,我們可以簡單模擬一下緩存的實現(xiàn),本文通過示例代碼介紹的非常詳細,感興趣的朋友一起看看吧

Java 實現(xiàn)緩存的三種方式

一、HashMap實現(xiàn)緩存

? 可以實現(xiàn)簡單的本地緩存,但是實際開發(fā)中不推薦,我們可以簡單模擬一下緩存的實現(xiàn),

Step-1:實現(xiàn)一個緩存管理類

public class LocalCache {
    public static HashMap<String,String> cache = new HashMap<>();
    static {
        String name = UUID.randomUUID().toString();
        LocalCache.cache.put(String.valueOf(1),name);
        System.out.println("id為1的數(shù)據(jù)添加到了緩存");
    }
}
// 類中有 `static` 修飾的靜態(tài)代碼塊,當類被加載的時候就會執(zhí)行,如有不懂的可以如下博客
// https://blog.csdn.net/weixin_62636014/article/details/136851287

Tips:我們在static中完成了對緩存的初始化,你可以往緩存里面放入初始數(shù)據(jù)。

Step-2:將緩存管理類交給 Spring 進行管理

@Component
public class LocalCache {
    public static HashMap<String,String> cache = new HashMap<>();
    static {
        String name = UUID.randomUUID().toString();
        LocalCache.cache.put(String.valueOf(1),name);
        System.out.println("id為1的數(shù)據(jù)添加到了緩存");
    }
    @PostConstruct
    public void init() {
        String name = UUID.randomUUID().toString();
        LocalCache.cache.put(String.valueOf(2),name);
        System.out.println("id為2的數(shù)據(jù)添加到了緩存");
    }
}

Tips:在將緩存管理類交給了 Spring進行管理后,在方法上加入@PostConstruct,可以使方法默認執(zhí)行,注意該注解不是 Spring 框架提供,僅僅是由 Java JDK 提供的,主要是作用于 Servlet生命周期的注解,實現(xiàn)的是在 Bean 初始化之前自定義操作

@PostConstruct 方法在 Bean初始化中的執(zhí)行順序

  • Constructor(構(gòu)造方法)
  • @Autowired(依賴注入)
  • @PostConstruct (注釋的初始化方法)

Step-3:編寫接口測試緩存

@RequestMapping("test")
public String test(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("緩存中不存在,查詢數(shù)據(jù)庫");
    // 查詢數(shù)據(jù)庫操作后,queryDataName方法沒有寫了;
    // 大家可以自己配一下Mybatis和JDBC進行數(shù)據(jù)庫查詢,達到效果是從庫中查出來 name;
    name = queryDataName(id);
    System.out.println(name);
    LocalCache.cache.put(String.valueOf(id),name);
    return name;
}
public String queryDataName(Long id) {
    String name = UUID.randomUUID().toString();
    return name;
}

Step-4:結(jié)果展示

? 這個是控制臺輸出,每個人的隨機 UUID 不一致,我這個只是一個樣例

id為1的數(shù)據(jù)添加到了緩存
id為2的數(shù)據(jù)添加到了緩存
緩存中存在,查詢緩存
e2eadabe-3c42-4732-b465-e085ea5faf96
緩存中不存在,查詢數(shù)據(jù)庫
942ffe92-454f-4046-87e5-53e8b951d2a1

二、guava local cache 實現(xiàn)

TipsGuavaGoogle提供的一套Java工具包,Guava Cache是一套非常完善的本地緩存機制(JVM緩存),工具類就是封裝平常常用的方法,不需要你重復(fù)造輪子,節(jié)省開發(fā)人員時間,我們一般需要知道怎么使用。其設(shè)計來源于 CurrentHashMap,可以按照多種策略來清理存儲在其中的緩存值且保持很高的并發(fā)讀寫性能。

Guava 提供以下方面的能力

  • 集合 [collections]
  • 緩存 [caching]
  • 原生類型支持 [primitives support]
  • 并發(fā)庫 [concurrency libraries]
  • 通用注解 [common annotations]
  • 字符串處理 [string processing]
  • I/O 等等。

Step-1:導(dǎo)入guava 依賴

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

Step-2:使用guava創(chuàng)建簡單緩存管理類

為了方便展示,這里面使用了5 秒的緩存保留時間。

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()
        //設(shè)置緩存初始大小,應(yīng)該合理設(shè)置,后續(xù)會擴容
        .initalCapacity(10)
        //最大值
        .maximumSize(100)
        //并發(fā)數(shù)設(shè)置
        .concurrencyLevel(5)
        //緩存過期時間,寫入后5秒鐘過期
        .expireAfterWrite(5,TimeUnit.SECONDS)
        //統(tǒng)計緩存命中率
        .recordStats()
        .build()
    public Cache<String,String> getFiveSecondCache() {
        return fiveSecondCache;
    } // 這里就是拿到緩存對象。
    public void setFiveSecondCache(Cache<String,String> fiveSecondCache) {
        this.fiveSecondCache = fiveSecondCache;
    }
}

Step-3:使用 guava cache,并嘗試統(tǒng)計命中率

public class test {
    @Autowired
    private 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;
        }
        // 將數(shù)據(jù)存入緩存
        System.out.println("緩存未命中," + getCacheStats(fiveSecondCache));
        nameCache = id + "-" + UUID.randomUUID().toString();
        fiveSecondCache.put(String.valueOf(id),nameCache);
        return nameCache;
    }
    public String getCacheStats(Cache<String,String> cahce) {
        CacheStats stats = cache.stats();
        return "緩沖命中率:"+stats.hitRate() +" 被清除緩沖數(shù):" + stats.evictionCount();
    }
}

三、使用redis實現(xiàn)緩存

TipsRedis (全稱: Remote Dictionary Server 遠程字典服務(wù))是一個開源的使用 ANSI C語言 編寫、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、 Key-Value數(shù)據(jù)庫 。Redis 一般被用來做緩存用的,它實際上也是一種數(shù)據(jù)庫(非關(guān)系型數(shù)據(jù)庫),可以對經(jīng)常使用到的數(shù)據(jù)進行存儲,也就是大家所說的緩存。官方給出的數(shù)據(jù)是, Redis 能達到 10w+QPS( 每秒查詢速度 ) 。

Tips: 為什么 Redis 的速度比 Mysql 等這種數(shù)據(jù)快呢?

? 因為 Redis 存儲的是 key-values 格式的數(shù)據(jù),時間復(fù)雜度是 O(1) ,即直接通過 key 查詢對應(yīng)的 value 。 而如 Mysql 數(shù)據(jù)庫,底層的實現(xiàn)是 B+ 樹,時間復(fù)雜度是 O(logn) 。

? 最重要的一點是,數(shù)據(jù)庫的數(shù)據(jù)是存儲在磁盤中的,而 Redis 是存儲在內(nèi)存當中的,它們的速度差距不言而喻。但 Redis 也支持持久化存儲

Step-1:導(dǎo)入Redis 依賴

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

SpringBoot 配置文件中加入設(shè)置,我使用的是yml 形式的文件,如果沒有密碼的話不填就好了

  redis:
    # IP地址
    host: XXX.XXX.XXX.XXX
    # 密碼
    password: XXXXXXXX
    # 端口,默認為6379
    port: 6379
    # 數(shù)據(jù)庫索引
    database: 0
    # 連接超時時間
    timeout: 10s
    lettuce:
      pool:
        # 連接池中的最小空閑連接
        min-idle: 1
        # 連接池中的最大空閑連接
        max-idle: 8
        # 連接池的最大數(shù)據(jù)庫連接數(shù)
        max-active: 8
        # #連接池最大阻塞等待時間(使用負值表示沒有限制)
        max-wait: -1ms

Step-2:編寫測試接口

public class TestRedis{
    // 下面StringRedisTemplate 是一個繼承自 RedisTemplate的類
    @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("緩存中不存在,查詢數(shù)據(jù)庫");
        name = id + "-" + UUID.randomUUID().toString();
        System.out.println(name);
        stringRedisTemplate.opsForValue().set(String.valueOf(id),name);
        return name;
    }
}

Step-3:進行接口測試,并使用Redis DeskTop Manager 進行查看

參考文章 

  1. 【java緩存、redis緩存、guava緩存】java中實現(xiàn)緩存的幾種方式_java緩存cache-CSDN博客
  2. 一篇文章搞定 Redis 基礎(chǔ)知識 - 知乎 (zhihu.com)
  3. Java本地緩存技術(shù)選型(Guava Cache、Caffeine、Encache) - 掘金 (juejin.cn)
  4. MemCache原理超詳細解讀(僅學習) - 知乎 (zhihu.com)
  5. PostConstruct注解詳細使用說明及理解-CSDN博客
  6. PostConstruct (Java Platform SE 8 ) (oracle.com)
  7. Java開發(fā)利器Guava Cache之使用篇 - 掘金 (juejin.cn)
  8. Google guava 工具類的介紹和使用 - 掘金 (juejin.cn)
  9. Redis詳細介紹(精簡版)_redis 服務(wù) 精簡-CSDN博客
  10. 初識Redis,看這一篇就夠了

到此這篇關(guān)于Java 實現(xiàn)緩存的三種方式問題匯總的文章就介紹到這了,更多相關(guān)Java 實現(xiàn)緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java類和對象習題及詳細答案解析

    Java類和對象習題及詳細答案解析

    這篇文章主要介紹了Java類和對象的相關(guān)知識,包括局部變量初始化、靜態(tài)方法、靜態(tài)導(dǎo)入、構(gòu)造方法、代碼塊執(zhí)行順序、toString方法重寫、類變量和靜態(tài)成員變量的訪問等,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-02-02
  • Java高效實現(xiàn)excel轉(zhuǎn)pdf(支持帶圖片的轉(zhuǎn)換)

    Java高效實現(xiàn)excel轉(zhuǎn)pdf(支持帶圖片的轉(zhuǎn)換)

    這篇文章主要為大家詳細介紹了如何用java實現(xiàn)excel轉(zhuǎn)pdf文件,并且支持excel單元格中帶有圖片的轉(zhuǎn)換,文中的示例代碼講解詳細,需要的可以參考下
    2024-01-01
  • 基于Redisson實現(xiàn)注解式分布式鎖的示例代碼

    基于Redisson實現(xiàn)注解式分布式鎖的示例代碼

    這篇文章主要為大家詳細介紹了如何基于Redisson實現(xiàn)注解式分布式鎖,文中的示例代碼講解詳細,具有一定的參考價值,需要的可以了解一下
    2023-07-07
  • 如何獲取MyBatis Plus執(zhí)行的完整的SQL語句

    如何獲取MyBatis Plus執(zhí)行的完整的SQL語句

    這篇文章主要介紹了如何獲取MyBatis Plus執(zhí)行的完整的SQL語句問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Spring動態(tài)管理定時任務(wù)之ThreadPoolTaskScheduler解讀

    Spring動態(tài)管理定時任務(wù)之ThreadPoolTaskScheduler解讀

    這篇文章主要介紹了Spring動態(tài)管理定時任務(wù)之ThreadPoolTaskScheduler解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • SpringBoot中使用@Value注解注入詳解

    SpringBoot中使用@Value注解注入詳解

    這篇文章主要介紹了SpringBoot中的@Value注入詳解,在SpringBoot中,@Value注解可以注入一些字段的普通屬性,并且會自動進行類型轉(zhuǎn)換,本文對這些類型進行總結(jié),需要的朋友可以參考下
    2023-08-08
  • Spring Boot 項目創(chuàng)建的詳細步驟(圖文)

    Spring Boot 項目創(chuàng)建的詳細步驟(圖文)

    這篇文章主要介紹了Spring Boot 項目創(chuàng)建的詳細步驟(圖文),這里我們有兩種創(chuàng)建Spring Boot項目的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • 理解java多線程中ExecutorService使用

    理解java多線程中ExecutorService使用

    這篇文章主要幫助大家理解java多線程中ExcetorServiced的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • SpringBoot單點登錄實現(xiàn)過程詳細分析

    SpringBoot單點登錄實現(xiàn)過程詳細分析

    這篇文章主要介紹了SpringBoot單點登錄實現(xiàn)過程,單點登錄英文全稱Single?Sign?On,簡稱就是SSO。它的解釋是:在多個應(yīng)用系統(tǒng)中,只需要登錄一次,就可以訪問其他相互信任的應(yīng)用系統(tǒng)
    2022-12-12
  • java設(shè)計模式系列之裝飾者模式

    java設(shè)計模式系列之裝飾者模式

    這篇文章主要為大家詳細介紹了java設(shè)計模式之裝飾者模式,裝飾者模式是一種結(jié)構(gòu)式模式,感興趣的朋友可以參考一下
    2016-02-02

最新評論