首頁  >  文章  >  Java  >  Java 快取技術中的快取懶加載

Java 快取技術中的快取懶加載

王林
王林原創
2023-06-20 12:24:101391瀏覽

Java 快取技術中的快取懶載入

在 Java 圈子中,快取技術是非常常見的技術。快取的作用就是為了提高資料存取的效能,避免重複計算和重複請求。快取技術的應用場景非常廣泛,特別是在一些需要頻繁存取資料的應用程式中,如電商網站、新聞入口網站、社群應用程式等等。

然而,快取技術也有一些缺點,例如:快取的初始化和更新可能會消耗大量的時間和效能資源。因此,為了提高快取的效能和效率,有一種稱為「快取懶加載」的技術應運而生,它可以有效地解決快取初始化和更新的問題,從而提高系統的效能和效率。

什麼是快取懶載入?

快取懶加載,就是指延遲初始化快取數據,等待第一次訪問時再加載數據到快取中。這種技術的優點是可以避免不必要的初始化和更新操作,從而降低系統的開銷和資源消耗。當然,快取懶載入的缺點是第一次造訪時可能會造成一些延遲,但是在大多數應用程式場景中,這種延遲是可以​​接受的。因此,快取懶載入技術在許多應用中都是非常常用的技術。

快取懶載入的實作方式

在 Java 中,快取懶載入的實作方式有很多種,這裡我們介紹幾種常見的實作方式。

方式一:使用 ConcurrentHashMap 和 Future 實作

ConcurrentHashMap 是 JDK 1.5 引入的執行緒安全的哈希表,可以用來儲存快取數據,而 Future 則可以用來非同步載入資料。

具體實作方式如下:

public class MyCache {
    private final Map<String, Future<String>> cache = new ConcurrentHashMap<>();
    private final Function<String, String> loadDataFunction;

    public MyCache(Function<String, String> loadDataFunction) {
        this.loadDataFunction = loadDataFunction;
    }

    public String getData(String key) throws ExecutionException, InterruptedException {
        Future<String> future = cache.get(key);

        if (future == null) {
            Callable<String> callable = () -> loadDataFunction.apply(key);
            FutureTask<String> futureTask = new FutureTask<>(callable);
            future = cache.putIfAbsent(key, futureTask);  
            if (future == null) {
                future = futureTask;
                futureTask.run();
            }
        }
        return future.get();
    }
}

這個實作方式比較簡單,大概的流程如下:

  1. 嘗試從快取中取得指定key 的Future 值;
  2. 如果Future 值為null,表示對應的數據沒有被緩存,則透過loadDataFunction 載入數據,並將其封裝成FutureTask 對象,插入到快取中;
  3. 如果插入成功(即之前沒有其他執行緒插入該key),則執行FutureTask 以非同步載入資料;
  4. 最後,傳回快取中指定key 對應的Future 值。

方式二:使用 Double-Checked Locking 實作

Double-Checked Locking 是一種常見的多執行緒程式設計技巧,可以避免重複的鎖定競爭,從而提高系統效能。在快取懶加載中,可以使用 Double-Checked Locking 技巧來實現延遲初始化的效果。

具體實作方式如下:

public class MyCache {
    private Map<String, String> cache = null;

    public String getData(String key) {
        String data = cache.get(key);
        if (data == null) {
            synchronized (this) {
                data = cache.get(key);

                if (data == null) {
                    data = loadData(key);
                    cache.put(key, data);
                }
            }
        }
        return data;
    }

    private String loadData(String key) {
        // TODO: load data from database or remote API
        return "data";
    }
}

這個實作方式比較簡單,大概的流程如下:

  1. 嘗試從快取中取得指定key 的值;
  2. 如果值為null,則執行synchronized 程式碼區塊;
  3. 在synchronized 程式碼區塊中,再次嘗試取得快取數據,如果依然為null,則呼叫loadData 方法載入數據,並將其儲存到快取中;
  4. 最後,傳回指定key 對應的資料。

方式三:使用 AtomicReference 實作

AtomicReference 是 JDK 1.5 引入的原子操作類,可以用來實現快取懶載入的效果。

具體實作方式如下:

public class MyCache {
    private final Map<String, String> cache = new ConcurrentHashMap<>();
    private final AtomicReference<Map<String, String>> reference =
            new AtomicReference<>(null);

    public String getData(String key) {
        Map<String, String> currentCache = reference.get();

        if (currentCache == null) {
            currentCache = cache;
            reference.compareAndSet(null, currentCache);
        }

        return currentCache.computeIfAbsent(key, k -> loadData(k));
    }

    private String loadData(String key) {
        // TODO: load data from database or remote API
        return "data";
    }
}

這個實作方式比較複雜,大概的流程如下:

    ##嘗試讀取引用指向的快取資料;
  1. 如果快取資料為null,則從ConcurrentHashMap 讀取數據,並將其作為原始資料存放到AtomicReference ;
  2. 然後,使用computeIfAbsent 方法從快取資料中取得指定key 對應的資料;
  3. 如果指定的key 對應的資料不存在,則呼叫loadData 方法載入數據,儲存到快取資料中,並傳回該資料。
使用快取懶載入可以帶來哪些好處?

使用快取懶載入技術可以帶來以下幾個好處:

    減少初始化和更新的開銷和資源消耗;
  1. 避免無用的運算和請求操作;
  2. 提高系統的回應速度和吞吐量;
  3. 減少系統的記憶體佔用和開銷;
  4. 提高系統的可維護性和可擴展性。
總結

在 Java 快取技術中,快取懶載入是一項非常實用的技術。透過延遲初始化快取數據,可以避免不必要的運算和請求操作,提高系統的效能和效率。本文介紹了幾種常見的快取懶載入實作方式,希望能幫助大家更深入地了解並掌握 Java 快取技術。

以上是Java 快取技術中的快取懶加載的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn