高效的緩存技術——LoadingCache的實現原理

一、概述

在現代軟體開發中,緩存是一種極為常見的性能優化手段。它可以將需要反覆獲取或計算的數據暫時保存在內存或磁碟等快速存儲介質中,以加速訪問和減少計算量。在緩存的實現中,LoadingCache是一種常用的緩存實現方式,它在多線程下能夠實現高效的緩存訪問和更新。本文將詳細介紹LoadingCache的實現原理。

二、LoadingCache的基本概念

Google Guava是一個Java編程庫,其中包含了許多高質量的工具類和方法。其中,Guava的緩存工具之一是LoadingCache。LoadingCache是一個帶有自動載入功能的緩存,可以自動載入緩存中不存在的數據。其實質是一個鍵值對(Key-Value Pair)的緩存,可以使用鍵來獲取相應的值。

三、LoadingCache的核心介面

在Guava中使用LoadingCache時,主要要關注兩個介面:CacheLoader和LoadingCache。其中,CacheLoader承擔的是將鍵映射到值的查詢邏輯工作,而LoadingCache是CacheLoader的衍生介面。它增加了一些額外的操作,如自動載入、非同步載入、緩存刷新等。

首先,定義一下CacheLoader介面及其方法:

public interface CacheLoader {
    V load(K key) throws Exception;
}

其中K代表鍵的類型,V代表值的類型。load()方法即為查詢邏輯方法,接收一個Key作為參數,返回與該Key相關的Value。如果CacheLoader邏輯中沒有命中該Key對應的Value,則將返回null。

接下來是LoadingCache介面及其方法:

public interface LoadingCache extends Cache {
    V get(K key) throws ExecutionException;
    ImmutableMap getAll(Iterable keys) throws ExecutionException;
    void refresh(K key);
    ConcurrentMap asMap();
}

其中Cache介面是LoadingCache的父介面,它定義了一些基本的緩存操作方法。而LoadingCache則增加了一些自動載入、緩存刷新等操作。

get(K key)方法定義了默認的基本緩存操作,如果Cache中不包含該Key對應的Value,將自動調用CacheLoader.load(K key)方法進行自動載入。如果沒有定義CacheLoader,將拋出一個UncheckedExecutionException異常。

getAll(Iterable<? extends K> keys)則擴展了get(K key),可以同時獲取多組Key-Value對的結果。

refresh(K key)方法可以對特定Key的Value進行刷新,即調用對應Key的CacheLoader.load(K key)重新載入並替換原值。

asMap()方法則返回對應的ConcurrentMap對象,可以使用常規的Map方法來對緩存中的數據進行操作。

四、LoadingCache的緩存策略

在緩存中,緩存策略是一個重要的問題。Guava的LoadingCache提供了多種緩存策略供使用,具體如下:

1. 基本緩存策略

Guava提供的基本緩存策略有兩種,分別是基於大小的緩存和基於時間的緩存。

基於大小的緩存是指,當緩存中的Key-Value對數量超出一定的限制時,LoadingCache會自動剔除舊的Key-Value對,以保持緩存大小不超過限制。可以使用maximumSize(long)方法來指定緩存的最大大小,如:

LoadingCache cache = 
    CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() {
        public String load(String key) throws Exception {
            return key + "->value";
        }
    });

基於時間的緩存是指,當緩存中的Key-Value對超過限制時間後,LoadingCache會自動剔除該Key-Value對。可以使用expireAfterWrite(long, TimeUnit)方法來指定緩存過期時間。如:

LoadingCache cache = 
    CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).build(new CacheLoader() {
        public String load(String key) throws Exception {
            return key + "->value";
        }
    });

2. 基於引用的緩存策略

基於引用的緩存策略是指,緩存中的Key-Value對的引用關係從而被決定是否從緩存中清除。Guava提供了兩種基於引用的緩存策略,分別是弱引用和軟引用。

弱引用是指,當Java虛擬機的垃圾回收器掃描到該Key-Value對的Key只被弱引用引用時,將自動從緩存中清除該Key-Value對。可以使用weakKeys()方法啟用弱引用:

LoadingCache cache = 
    CacheBuilder.newBuilder().weakKeys().build(new CacheLoader() {
        public String load(String key) throws Exception {
            return key + "->value";
        }
    });

軟引用是指,當Java虛擬機的垃圾回收器掃描到該Key-Value對的Key被軟引用引用並且內存不足時,將自動從緩存中清除該Key-Value對。可以使用softValues()方法啟用軟引用:

LoadingCache cache = 
    CacheBuilder.newBuilder().softValues().build(new CacheLoader() {
        public String load(String key) throws Exception {
            return key + "->value";
        }
    });

3. 基於提醒的緩存策略

基於提醒的緩存策略是指,緩存中的Key-Value對在特定條件下會被自動剔除。Guava提供了兩種基於提醒的緩存策略,分別是基於寫入提醒和基於訪問提醒。其中,寫入提醒是指,在寫入某個Key-Value對時,通知外部任務,以便執行對該Key-Value對的一些處理。訪問提醒是指,在特定PerformFunction上訪問一個Key-Value對時,通知外部任務,以便記錄下該Key-Value對的訪問情況。可以使用CacheBuilder提供的removalListener(RemovalListener)方法來啟用緩存的提醒策略。

下面是寫入提醒的例子:

Cache cache =
        CacheBuilder.newBuilder()
                .maximumSize(1000).recordStats()
                .removalListener(new RemovalListener() {
                    public void onRemoval(RemovalNotification removalNotification) {
                        System.out.println(removalNotification.getKey() + " was removed, cause is " + removalNotification.getCause());
                    }
                }).build();

五、LoadingCache的線程安全實現

一個緩存框架的線程安全是非常重要的。Guava的LoadingCache在多線程操作時,是線程安全的。在它的內部實現中使用了ConcurrentHashMap作為容器,對緩存的更新和讀取都使用了並發鎖機制。

以下是一個LoadingCache的多線程並發示例:

public class LoadingCacheTest {

    private static final LoadingCache CACHE = CacheBuilder.newBuilder()
            .maximumSize(100)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .refreshAfterWrite(1, TimeUnit.MINUTES)
            .build(new CacheLoader() {
                public String load(String key) throws Exception {
                    return key + "->loaded";
                }
            });

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 100; i++) {
                    try {
                        System.out.println(Thread.currentThread().getName() + ": " + CACHE.get("key"));
                        TimeUnit.MILLISECONDS.sleep(50L);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "Thread-1").start();

        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 50; i++) {
                    try {
                        System.out.println(Thread.currentThread().getName() + ": " + CACHE.get("key2"));
                        TimeUnit.MILLISECONDS.sleep(100L);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "Thread-2").start();
    }
}

六、總結

本文詳細介紹了Google Guava中的LoadingCache的實現原理。LoadingCache是一種帶有自動載入功能的緩存,可以實現高效的緩存訪問和更新。在使用LoadingCache時,要熟悉其核心介面和各種緩存策略,以及線程安全的問題。同時,在實際使用LoadingCache時,需要根據具體的業務場景和數據特點制定相應的緩存策略和CacheLoader處理邏輯。

原創文章,作者:ULZVW,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/329111.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
ULZVW的頭像ULZVW
上一篇 2025-01-14 18:55
下一篇 2025-01-14 18:55

相關推薦

  • Harris角點檢測演算法原理與實現

    本文將從多個方面對Harris角點檢測演算法進行詳細的闡述,包括演算法原理、實現步驟、代碼實現等。 一、Harris角點檢測演算法原理 Harris角點檢測演算法是一種經典的計算機視覺演算法…

    編程 2025-04-29
  • Python熱重載技術

    Python熱重載技術是現代編程的關鍵功能之一。它可以幫助我們在程序運行的過程中,更新代碼而無需重新啟動程序。本文將會全方位地介紹Python熱重載的實現方法和應用場景。 一、實現…

    編程 2025-04-29
  • 瘦臉演算法 Python 原理與實現

    本文將從多個方面詳細闡述瘦臉演算法 Python 實現的原理和方法,包括該演算法的意義、流程、代碼實現、優化等內容。 一、演算法意義 隨著科技的發展,瘦臉演算法已經成為了人們修圖中不可缺少…

    編程 2025-04-29
  • Python 數據緩存及其應用

    本文將為大家詳細介紹Python數據緩存,並提供相關代碼示例。 一、Python 數據緩存基礎概念 Python 是一種解釋型語言,每次執行完一條語句後就會將內存中的結果清空,如果…

    編程 2025-04-29
  • Python緩存圖片的處理方式

    本文將從多個方面詳細闡述Python緩存圖片的處理方式,包括緩存原理、緩存框架、緩存策略、緩存更新和緩存清除等方面。 一、緩存原理 緩存是一種提高應用程序性能的技術,在網路應用中流…

    編程 2025-04-29
  • 神經網路BP演算法原理

    本文將從多個方面對神經網路BP演算法原理進行詳細闡述,並給出完整的代碼示例。 一、BP演算法簡介 BP演算法是一種常用的神經網路訓練演算法,其全稱為反向傳播演算法。BP演算法的基本思想是通過正…

    編程 2025-04-29
  • Python包絡平滑技術解析

    本文將從以下幾個方面對Python包絡平滑技術進行詳細的闡述,包括: 什麼是包絡平滑技術? Python中使用包絡平滑技術的方法有哪些? 包絡平滑技術在具體應用中的實際效果 一、包…

    編程 2025-04-29
  • parent.$.dialog是什麼技術的語法

    parent.$.dialog是一種基於jQuery插件的彈出式對話框技術,它提供了一個方便快捷的方式來創建各種類型和樣式的彈出式對話框。它是對於在網站開發中常見的彈窗、提示框等交…

    編程 2025-04-28
  • 微信小程序重構H5技術方案設計 Github

    本文旨在探討如何在微信小程序中重構H5技術方案,以及如何結合Github進行代碼存儲和版本管理。我們將從以下幾個方面進行討論: 一、小程序與H5技術對比 微信小程序與H5技術都可以…

    編程 2025-04-28
  • Trocket:打造高效可靠的遠程控制工具

    如何使用trocket打造高效可靠的遠程控制工具?本文將從以下幾個方面進行詳細的闡述。 一、安裝和使用trocket trocket是一個基於Python實現的遠程控制工具,使用時…

    編程 2025-04-28

發表回復

登錄後才能評論