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

Java實(shí)現(xiàn)本地緩存的四種方法實(shí)現(xiàn)與對比

 更新時間:2025年08月15日 08:49:47   作者:橘子編程  
本地緩存的優(yōu)點(diǎn)就是速度非???沒有網(wǎng)絡(luò)消耗,本地緩存比如 caffine,guava cache 這些都是比較常用的,下面我們來看看這四種緩存的具體實(shí)現(xiàn)吧

本地緩存比如 caffine,guava cache 這些都是比較常用的,本地緩存的優(yōu)點(diǎn)就是速度非??欤瑳]有網(wǎng)絡(luò)消耗,缺點(diǎn)就是應(yīng)用重啟后,緩存就會丟失。

Java緩存技術(shù)可分為遠(yuǎn)端緩存和本地緩存,遠(yuǎn)端緩存常用的方案有著名的redis,而本地緩存的代表技術(shù)主要有HashMap,Guava Cache,Caffeine和Encahche。

1、HashMap

通過Map的底層方式,直接將需要緩存的對象放在內(nèi)存中。

  • 優(yōu)點(diǎn):簡單粗暴,不需要引入第三方包,比較適合一些比較簡單的場景。
  • 缺點(diǎn):沒有緩存淘汰策略,定制化開發(fā)成本高。
package com.taiyuan.javademoone.cachedemo;
 
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
 
/**
 * 定義一個基于LinkedHashMap實(shí)現(xiàn)的線程安全的LRU緩存類
 */
public class LRUCache extends LinkedHashMap<Object, Object> {  // 明確泛型類型為<Object, Object>,提高代碼可讀性
    /**
     * 可重入讀寫鎖,用于保證多線程環(huán)境下對緩存的并發(fā)讀寫操作的安全性
     */
    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private Lock readLock = readWriteLock.readLock();   // 讀鎖,用于并發(fā)讀取時共享訪問
    private Lock writeLock = readWriteLock.writeLock(); // 寫鎖,用于寫入或修改時獨(dú)占訪問
 
    /**
     * 緩存的最大容量限制,超過此容量將移除最久未使用的條目
     */
    private int maxSize;
 
    /**
     * 構(gòu)造函數(shù),初始化LRU緩存并設(shè)置最大容量
     *
     * @param maxSize 緩存允許存儲的最大條目數(shù)
     */
    public LRUCache(int maxSize) {
        // 調(diào)用父類LinkedHashMap的構(gòu)造方法:
        // 參數(shù)1:初始容量為maxSize + 1,避免頻繁擴(kuò)容
        // 參數(shù)2:負(fù)載因子為1.0f,表示哈希表填滿到100%時才擴(kuò)容
        // 參數(shù)3:accessOrder為true,表示按照訪問順序排序,實(shí)現(xiàn)LRU策略
        super(maxSize + 1, 1.0f, true);
        this.maxSize = maxSize;
    }
 
    /**
     * 重寫get方法,獲取指定key對應(yīng)的value,使用讀鎖保證線程安全
     *
     * @param key 要查找的鍵
     * @return 對應(yīng)的值,如果不存在則返回null
     */
    @Override
    public Object get(Object key) {
        readLock.lock();      // 加讀鎖,允許多個線程同時讀
        try {
            return super.get(key); // 調(diào)用父類的get方法
        } finally {
            readLock.unlock(); // 確保讀鎖最終被釋放
        }
    }
 
    /**
     * 重寫put方法,向緩存中添加或更新鍵值對,使用寫鎖保證線程安全
     *
     * @param key   要插入或更新的鍵
     * @param value 要插入或更新的值
     * @return 之前與key關(guān)聯(lián)的值,如果沒有則返回null
     */
    @Override
    public Object put(Object key, Object value) {
        writeLock.lock();     // 加寫鎖,確保同一時間只有一個線程可以寫
        try {
            return super.put(key, value); // 調(diào)用父類的put方法
        } finally {
            writeLock.unlock(); // 確保寫鎖最終被釋放
        }
    }
 
    /**
     * 重寫removeEldestEntry方法,當(dāng)緩存大小超過maxSize時,移除最久未使用的條目
     *
     * @param eldest 最久未訪問的鍵值對Entry
     * @return 如果當(dāng)前緩存大小超過最大容量,則返回true,觸發(fā)刪除最老的條目;否則返回false
     */
    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return this.size() > maxSize; // 判斷當(dāng)前緩存大小是否超出限制
    }
 
 
 
    // 測試主方法
    public static void main(String[] args) {
        LRUCache cache = new LRUCache(3);
        cache.put("1", "one");
        cache.put("2", "two");
        cache.put("3", "three");
        System.out.println(cache); // 輸出:{1=one, 2=two, 3=three}
    }
}

2、Guava Cache

Guava Cache 是 Google Guava 庫中的一個本地緩存實(shí)現(xiàn),它提供了以下主要特性:

  • 自動加載:當(dāng)緩存未命中時自動從指定來源加載數(shù)據(jù)
  • 多種淘汰策略:支持基于大小、時間和引用的淘汰
  • 統(tǒng)計功能:內(nèi)置緩存命中率統(tǒng)計
  • 線程安全:內(nèi)置并發(fā)控制機(jī)制
  • 監(jiān)聽器:支持緩存移除通知
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>33.4.8-jre</version>
</dependency>
package com.helloworld.demo;
 
import com.google.common.cache.*;
 
import java.util.concurrent.TimeUnit;
 
public class GuavaCacheExample {
    public static void main(String[] args) {
        // 創(chuàng)建一個Guava的LoadingCache實(shí)例,支持自動加載緩存項(xiàng)
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(100)                     // 設(shè)置緩存最大容量為100個條目
                .expireAfterWrite(10, TimeUnit.MINUTES) // 設(shè)置緩存項(xiàng)在寫入10分鐘后自動過期
                .recordStats()                         // 開啟緩存統(tǒng)計功能,可以獲取命中率等信息
                .build(new CacheLoader<String, String>() { // 定義緩存未命中時的加載邏輯
                    @Override
                    public String load(String key) throws Exception {
                        // 當(dāng)根據(jù)key獲取不到緩存值時,調(diào)用此方法從數(shù)據(jù)源(如數(shù)據(jù)庫)加載數(shù)據(jù)
                        return fetchDataFromDatabase(key);
                    }
                });
 
        try {
            // 第一次獲取key為"user:1001"的值,由于緩存中沒有,會觸發(fā)load方法從數(shù)據(jù)庫加載
            System.out.println("第一次獲取(從數(shù)據(jù)庫加載): " + cache.get("user:1001"));
            // 第二次獲取相同的key,此時緩存中已有該值,直接從緩存返回,不會再次加載
            System.out.println("第二次獲取(從緩存獲取): " + cache.get("user:1001"));
 
            // 手動向緩存中放入一個鍵值對,繞過自動加載邏輯
            cache.put("user:1002", "Manual Data");
            // 獲取手動放入的緩存值
            System.out.println("手動放入的數(shù)據(jù): " + cache.get("user:1002"));
 
            // 打印緩存的統(tǒng)計信息,如命中率、加載次數(shù)等
            System.out.println("\n緩存統(tǒng)計:");
            System.out.println(cache.stats());
 
            // 手動移除指定key的緩存項(xiàng)
            cache.invalidate("user:1001");
            // 嘗試獲取已被移除的緩存項(xiàng),返回null表示不存在
            System.out.println("\n移除后獲取: " + cache.getIfPresent("user:1001"));
 
        } catch (Exception e) {
            e.printStackTrace(); // 捕獲并打印異常信息
        }
    }
 
    // 模擬從數(shù)據(jù)庫中根據(jù)key獲取數(shù)據(jù)的邏輯
    private static String fetchDataFromDatabase(String key) {
        // 打印當(dāng)前正在加載的key,用于觀察加載行為
        System.out.println("正在從數(shù)據(jù)庫加載數(shù)據(jù): " + key);
        try {
            Thread.sleep(500); // 模擬數(shù)據(jù)庫查詢的延遲,增加真實(shí)感
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // 恢復(fù)中斷狀態(tài)
        }
        // 返回模擬的數(shù)據(jù)庫查詢結(jié)果
        return "Data for " + key;
    }
}

3、Caffeine

Caffeine采用了W-TinyLFU(LUR和LFU的優(yōu)點(diǎn)結(jié)合)開源的緩存技術(shù)。緩存性能接近理論最優(yōu),屬于是Guava Cache的增強(qiáng)版。

Caffeine 是一個高性能的 Java 緩存庫,它改進(jìn)了 Guava Cache 的設(shè)計,具有以下特點(diǎn):

  • 優(yōu)化的淘汰算法:采用 W-TinyLFU 算法,結(jié)合了 LRU 和 LFU 的優(yōu)點(diǎn)
  • 卓越的性能:讀寫性能接近理論最優(yōu)值
  • 異步支持:提供異步加載和刷新機(jī)制
  • 豐富的特性:支持多種淘汰策略、權(quán)重計算、統(tǒng)計等功能
  • 內(nèi)存友好:相比 Guava Cache 減少約 50% 的內(nèi)存占用
<dependency>
  <groupId>com.github.ben-manes.caffeine</groupId>
  <artifactId>caffeine</artifactId>
  <version>2.9.3</version>
</dependency>
package com.helloworld.demo;
 
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
 
import java.util.concurrent.TimeUnit;
 
public class CaffeineCacheTest {
    public static void main(String[] args) throws Exception {
        // 創(chuàng)建一個 Caffeine 緩存實(shí)例(注意:原注釋寫的是 Guava Cache,實(shí)際使用的是 Caffeine)
        Cache<String, String> loadingCache = Caffeine.newBuilder()
                .initialCapacity(5) // 設(shè)置初始緩存容量為 5 個條目
                .maximumSize(10)    // 設(shè)置緩存最大容量為 10 個條目,超過時將按照策略淘汰
                .expireAfterWrite(17, TimeUnit.SECONDS) // 寫入后 17 秒過期
                .expireAfterAccess(17, TimeUnit.SECONDS) // 最后一次訪問后 17 秒過期
                .build(); // 構(gòu)建緩存實(shí)例
 
        String key = "key"; // 定義緩存的鍵
        loadingCache.put(key, "這是測試方法"); // 手動將鍵值對放入緩存
        // 從緩存中獲取指定鍵的值
        String value = loadingCache.getIfPresent(key);
        System.out.println(" 從緩存中獲取指定鍵(key)的值:" + value); // 輸出:這是測試方法
 
        // 將指定的鍵從緩存中移除(使其失效)
        loadingCache.invalidate(key);
        value = loadingCache.getIfPresent(key);
        System.out.println(" 從緩存中獲取指定鍵(key)的值:" + value); // 輸出:null
    }
 
}

4、Encache

Ehcache是一個純java的進(jìn)程內(nèi)緩存框架,具有快速、精干的特點(diǎn)。是hibernate默認(rèn)的cacheprovider。

  • 優(yōu)點(diǎn):支持多種緩存淘汰算法,包括LFU,LRU和FIFO;緩存支持堆內(nèi)緩存,堆外緩存和磁盤緩存;支持多種集群方案,解決數(shù)據(jù)共享問題。
  • 缺點(diǎn):性能比Caffeine差
<dependency>
  <groupId>org.ehcache</groupId>
  <artifactId>ehcache</artifactId>
  <version>3.10.8</version>
</dependency>
package com.helloworld.demo;
 
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.MemoryUnit;
 
/**
 * Ehcache 基礎(chǔ)使用示例類
 */
public class EhcacheBasicExample {
    public static void main(String[] args) {
        // 1. 創(chuàng)建緩存管理器(CacheManager),它是管理所有緩存的核心對象
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
        // 初始化緩存管理器,使其可以開始工作
        cacheManager.init();
 
        // 2. 創(chuàng)建一個緩存配置,定義緩存的鍵值類型和存儲策略
        CacheConfigurationBuilder<String, String> config = CacheConfigurationBuilder
        .newCacheConfigurationBuilder(
            String.class,         // 緩存鍵的類型為 String
            String.class,         // 緩存值的類型為 String
            ResourcePoolsBuilder.heap(100) // 配置堆內(nèi)內(nèi)存緩存最多存儲 100 個條目
        );
 
        // 3. 根據(jù)配置創(chuàng)建一個名為 "myCache" 的緩存實(shí)例
        Cache<String, String> myCache = cacheManager.createCache("myCache", config);
 
        // 4. 使用緩存:存儲和讀取數(shù)據(jù)
        myCache.put("key1", "value1");          // 往緩存中放入一個鍵值對
        String value = myCache.get("key1");     // 從緩存中根據(jù) key 獲取對應(yīng)的 value
        System.out.println("獲取的值: " + value); // 打印獲取到的緩存值
 
        // 5. 使用完緩存后,關(guān)閉緩存管理器以釋放資源
        cacheManager.close();
    }
}

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

相關(guān)文章

  • mybatis-generator生成多次重復(fù)代碼問題以及解決

    mybatis-generator生成多次重復(fù)代碼問題以及解決

    在使用MySQL數(shù)據(jù)庫時,如果多個數(shù)據(jù)庫中存在相同表名,即使在URL中配置了數(shù)據(jù)庫名,也可能導(dǎo)致數(shù)據(jù)互相影響,解決這一問題的方法是在mapper-generator-config.xml文件中添加catalog屬性,明確指定逆向工程代碼所涉及表的數(shù)據(jù)庫名
    2024-10-10
  • Spring @Scheduled注解及工作原理

    Spring @Scheduled注解及工作原理

    Spring的@Scheduled注解用于標(biāo)記定時任務(wù),無需額外庫,需配置@EnableScheduling,設(shè)置fixedRate、fixedDelay或cron,基于TaskScheduler,默認(rèn)使用線程池,可自定義線程數(shù)及名稱以優(yōu)化性能,本文給大家介紹Spring @Scheduled注解的相關(guān)知識,感興趣的朋友一起看看吧
    2025-06-06
  • Java線程之join_動力節(jié)點(diǎn)Java學(xué)院整理

    Java線程之join_動力節(jié)點(diǎn)Java學(xué)院整理

    join() 定義在Thread.java中,下文通過源碼分享join(),需要的朋友參考下吧
    2017-05-05
  • Java的Hibernate框架中集合類數(shù)據(jù)結(jié)構(gòu)的映射編寫教程

    Java的Hibernate框架中集合類數(shù)據(jù)結(jié)構(gòu)的映射編寫教程

    Hibernate可以將Java中幾個內(nèi)置的集合結(jié)構(gòu)映射為數(shù)據(jù)庫使用的關(guān)系模型,下面我們就來看一下Java的Hibernate框架中集合類數(shù)據(jù)結(jié)構(gòu)的映射編寫教程:
    2016-07-07
  • Java數(shù)據(jù)結(jié)構(gòu)優(yōu)先隊(duì)列實(shí)練

    Java數(shù)據(jù)結(jié)構(gòu)優(yōu)先隊(duì)列實(shí)練

    通常都把隊(duì)列比喻成排隊(duì)買東西,大家都很守秩序,先排隊(duì)的人就先買東西。但是優(yōu)先隊(duì)列有所不同,它不遵循先進(jìn)先出的規(guī)則,而是根據(jù)隊(duì)列中元素的優(yōu)先權(quán),優(yōu)先權(quán)最大的先被取出,這篇文章主要介紹了java優(yōu)先隊(duì)列的真題,感興趣的朋友一起看看吧
    2022-07-07
  • 關(guān)于synchronized有趣的同步問題

    關(guān)于synchronized有趣的同步問題

    今天小編就為大家分享一篇關(guān)于關(guān)于synchronized有趣的同步問題,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Mybatis 動態(tài)sql的編寫與開啟二級緩存

    Mybatis 動態(tài)sql的編寫與開啟二級緩存

    二級緩存是Mapper級別的緩存,多個SqlSession去操作同一個Mapper中的SQL語句,則這些SqlSession可以共享二級緩存,即二級緩存是跨SqlSession的,這篇文章主要介紹了Mybatis 動態(tài)sql的編寫|開啟二級緩存,需要的朋友可以參考下
    2023-02-02
  • Java中防止數(shù)據(jù)重復(fù)提交超簡單的6種方法

    Java中防止數(shù)據(jù)重復(fù)提交超簡單的6種方法

    在平時開發(fā)中,如果網(wǎng)速比較慢的情況下,用戶提交表單后,發(fā)現(xiàn)服務(wù)器半天都沒有響應(yīng),那么用戶可能會以為是自己沒有提交表單,就會再點(diǎn)擊提交按鈕重復(fù)提交表單,這篇文章主要給大家介紹了關(guān)于Java中防止數(shù)據(jù)重復(fù)提交超簡單的6種方法,需要的朋友可以參考下
    2021-11-11
  • Java線程組與未處理異常實(shí)例分析

    Java線程組與未處理異常實(shí)例分析

    這篇文章主要介紹了Java線程組與未處理異常,結(jié)合實(shí)例形式分析了java線程組處理異常的相關(guān)技巧與操作注意事項(xiàng),需要的朋友可以參考下
    2019-09-09
  • Java實(shí)現(xiàn)的數(shù)字簽名算法RSA完整示例

    Java實(shí)現(xiàn)的數(shù)字簽名算法RSA完整示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的數(shù)字簽名算法RSA,結(jié)合完整實(shí)例形式詳細(xì)分析了RSA算法的相關(guān)概念、原理、實(shí)現(xiàn)方法及操作技巧,需要的朋友可以參考下
    2019-09-09

最新評論