java中的本地緩存GuavaCache使用方法和示例教程
在現(xiàn)代互聯(lián)網(wǎng)應(yīng)用中,高并發(fā)場(chǎng)景是每個(gè)開(kāi)發(fā)者都可能遇到的挑戰(zhàn)。為了提高系統(tǒng)的響應(yīng)速度和吞吐量,緩存技術(shù)成為了一個(gè)不可或缺的部分。Google Guava庫(kù)提供了一個(gè)強(qiáng)大的本地緩存實(shí)現(xiàn)——GuavaCache,它不僅簡(jiǎn)單易用,而且性能優(yōu)秀,非常適合處理高并發(fā)場(chǎng)景。
GuavaCache簡(jiǎn)介
GuavaCache是Google Guava庫(kù)中的一個(gè)組件,用于實(shí)現(xiàn)內(nèi)存中的緩存。它支持多種配置選項(xiàng),如設(shè)置緩存大小、過(guò)期策略等,并且提供了線程安全的操作方法,使得在多線程環(huán)境中使用更加方便。
主要特性
線程安全
GuavaCache的所有操作都是線程安全的,這使得它在高并發(fā)環(huán)境下能夠穩(wěn)定運(yùn)行,無(wú)需額外的同步控制。
自動(dòng)加載
可以通過(guò)LoadingCache接口實(shí)現(xiàn)數(shù)據(jù)的自動(dòng)加載,當(dāng)緩存中沒(méi)有找到對(duì)應(yīng)的鍵時(shí),會(huì)自動(dòng)調(diào)用指定的方法來(lái)加載數(shù)據(jù)。
過(guò)期策略
支持基于時(shí)間的過(guò)期策略,包括創(chuàng)建后過(guò)期(expire after write)和訪問(wèn)后過(guò)期(expire after access)。
內(nèi)存回收
GuavaCache可以根據(jù)內(nèi)存情況自動(dòng)回收不常用的條目,避免內(nèi)存溢出。
使用示例
基本使用
首先,需要添加Guava庫(kù)到項(xiàng)目中,如果使用Maven,可以在pom.xml中添加如下依賴(lài):
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>接下來(lái),創(chuàng)建一個(gè)簡(jiǎn)單的緩存實(shí)例:
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class GuavaCacheExample {
public static void main(String[] args) throws ExecutionException {
// 創(chuàng)建一個(gè)LoadingCache實(shí)例
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(100) // 設(shè)置緩存的最大容量
.expireAfterWrite(10, TimeUnit.MINUTES) // 設(shè)置過(guò)期時(shí)間為10分鐘
.build(new CacheLoader<String, String>() { // 定義默認(rèn)的數(shù)據(jù)加載機(jī)制
@Override
public String load(String key) throws Exception {
return "value-" + key;
}
});
// 訪問(wèn)緩存
String value = cache.get("key1");
System.out.println(value); // 輸出: value-key1
}
}異常處理
在實(shí)際應(yīng)用中,數(shù)據(jù)加載可能會(huì)拋出異常。GuavaCache允許你定義如何處理這些異常:
try {
String value = cache.get("key2");
} catch (ExecutionException e) {
// 處理異常
System.err.println("Failed to load value for key2: " + e.getCause());
}手動(dòng)加載和刪除
除了自動(dòng)加載外,還可以手動(dòng)將數(shù)據(jù)放入緩存或從緩存中刪除數(shù)據(jù):
// 手動(dòng)加載
cache.put("key3", "value3");
// 手動(dòng)刪除
cache.invalidate("key3");性能優(yōu)化
并發(fā)級(jí)別
通過(guò)設(shè)置concurrencyLevel參數(shù)可以調(diào)整緩存的并發(fā)性能,這個(gè)值表示預(yù)計(jì)同時(shí)訪問(wèn)緩存的線程數(shù)。通常情況下,默認(rèn)值已經(jīng)足夠好,但在特定場(chǎng)景下適當(dāng)調(diào)整可以提升性能。
軟引用與弱引用
對(duì)于內(nèi)存敏感的應(yīng)用,可以考慮使用軟引用或弱引用來(lái)存儲(chǔ)緩存項(xiàng),這樣當(dāng)系統(tǒng)內(nèi)存不足時(shí),JVM會(huì)自動(dòng)回收這些對(duì)象。
CacheBuilder.newBuilder()
.softValues() // 使用軟引用
.weakKeys() // 使用弱引用
.build();GuavaCache是一個(gè)強(qiáng)大而靈活的緩存工具,特別適合于需要高性能和低延遲的應(yīng)用。通過(guò)合理配置,可以有效應(yīng)對(duì)高并發(fā)場(chǎng)景下的各種挑戰(zhàn)。這篇文章介紹了GuavaCache的基本概念、主要特性和使用方法,以及一些性能優(yōu)化的技巧,適合對(duì)緩存技術(shù)感興趣的開(kāi)發(fā)者閱讀。Guava Cache 是一個(gè)非常高效的本地緩存庫(kù),特別適合處理高并發(fā)場(chǎng)景。下面是一個(gè)使用 Guava Cache 的示例代碼,假設(shè)我們有一個(gè)需要頻繁查詢(xún)用戶信息的應(yīng)用場(chǎng)景。
場(chǎng)景描述
假設(shè)我們有一個(gè)用戶服務(wù),需要頻繁地從數(shù)據(jù)庫(kù)中查詢(xún)用戶信息。為了減少數(shù)據(jù)庫(kù)的訪問(wèn)壓力,我們可以使用 Guava Cache 來(lái)緩存用戶信息。
依賴(lài)引入
首先,確保你的項(xiàng)目中已經(jīng)引入了 Guava 庫(kù)。如果你使用的是 Maven,可以在 pom.xml 中添加以下依賴(lài):
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>示例代碼
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class UserCacheService {
// 創(chuàng)建一個(gè) Guava Cache 實(shí)例
private final Cache<String, User> userCache;
public UserCacheService() {
// 配置緩存
this.userCache = CacheBuilder.newBuilder()
.maximumSize(1000) // 最大緩存條目數(shù)
.expireAfterWrite(10, TimeUnit.MINUTES) // 緩存條目在寫(xiě)入后 10 分鐘過(guò)期
.recordStats() // 記錄緩存統(tǒng)計(jì)信息
.build();
}
// 獲取用戶信息
public User getUser(String userId) {
try {
return userCache.get(userId, () -> loadUserFromDatabase(userId));
} catch (ExecutionException e) {
throw new RuntimeException("Failed to load user from cache", e);
}
}
// 從數(shù)據(jù)庫(kù)加載用戶信息
private User loadUserFromDatabase(String userId) {
// 模擬從數(shù)據(jù)庫(kù)加載用戶信息
System.out.println("Loading user " + userId + " from database");
return new User(userId, "User Name " + userId);
}
public static void main(String[] args) {
UserCacheService service = new UserCacheService();
// 模擬高并發(fā)請(qǐng)求
for (int i = 0; i < 10; i++) {
new Thread(() -> {
User user = service.getUser("12345");
System.out.println("User: " + user);
}).start();
}
}
}
class User {
private String id;
private String name;
public User(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "User{id='" + id + "', name='" + name + "'}";
}
}代碼解釋
- 緩存配置:
maximumSize(1000):設(shè)置緩存的最大條目數(shù)為 1000。expireAfterWrite(10, TimeUnit.MINUTES):設(shè)置緩存條目在寫(xiě)入后 10 分鐘過(guò)期。recordStats():記錄緩存的統(tǒng)計(jì)信息,方便監(jiān)控和調(diào)試。
- 獲取用戶信息:
getUser方法通過(guò)userCache.get方法從緩存中獲取用戶信息。如果緩存中沒(méi)有該用戶信息,則調(diào)用loadUserFromDatabase方法從數(shù)據(jù)庫(kù)中加載用戶信息,并將其存入緩存。
- 從數(shù)據(jù)庫(kù)加載用戶信息:
loadUserFromDatabase方法模擬從數(shù)據(jù)庫(kù)中加載用戶信息的過(guò)程。
- 模擬高并發(fā)請(qǐng)求:
- 在
main方法中,創(chuàng)建多個(gè)線程模擬高并發(fā)請(qǐng)求,每個(gè)線程都嘗試獲取同一個(gè)用戶的用戶信息。由于緩存的存在,多次請(qǐng)求只會(huì)觸發(fā)一次數(shù)據(jù)庫(kù)查詢(xún)。
備注
1. 基本概念
- Cache:Guava Cache的主要接口,用于定義緩存的基本操作,如獲取、插入和刪除緩存項(xiàng)。
- LoadingCache:繼承自
Cache,提供了一種自動(dòng)加載數(shù)據(jù)到緩存中的機(jī)制,當(dāng)緩存中沒(méi)有請(qǐng)求的數(shù)據(jù)時(shí),可以自動(dòng)從數(shù)據(jù)源加載。 - RemovalListener:監(jiān)聽(tīng)器接口,用于監(jiān)聽(tīng)緩存項(xiàng)的移除事件,可以實(shí)現(xiàn)一些清理工作或日志記錄。
2. 創(chuàng)建Guava Cache
創(chuàng)建一個(gè)簡(jiǎn)單的GuavaCache可以通過(guò)CacheBuilder來(lái)完成。以下是一個(gè)基本的例子:
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
public class GuavaCacheExample {
public static void main(String[] args) {
// 創(chuàng)建一個(gè)最大容量為100,超過(guò)容量后使用LRU算法移除最近最少使用的條目,
// 并且設(shè)置10分鐘后過(guò)期的緩存
Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(10, TimeUnit.MINUTES)
.removalListener(notification -> System.out.println("Removed: " + notification.getKey()))
.build();
// 向緩存中添加數(shù)據(jù)
cache.put("key1", "value1");
// 從緩存中獲取數(shù)據(jù)
String value = cache.getIfPresent("key1");
System.out.println(value); // 輸出: value1
}
}3. 使用LoadingCache
LoadingCache可以在緩存未命中時(shí)自動(dòng)加載數(shù)據(jù),這通常通過(guò)實(shí)現(xiàn)CacheLoader來(lái)完成:
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class LoadingCacheExample {
public static void main(String[] args) throws ExecutionException {
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
return fetchFromDatabase(key);
}
});
// 獲取數(shù)據(jù),如果緩存中沒(méi)有,會(huì)自動(dòng)調(diào)用load方法加載
String value = cache.get("key1");
System.out.println(value); // 輸出: 從數(shù)據(jù)庫(kù)獲取的數(shù)據(jù)
}
private static String fetchFromDatabase(String key) {
// 模擬從數(shù)據(jù)庫(kù)查詢(xún)
return "從數(shù)據(jù)庫(kù)獲取的數(shù)據(jù)";
}
}4. 高級(jí)特性
- 統(tǒng)計(jì)信息:通過(guò)
cache.stats()可以獲得緩存的統(tǒng)計(jì)信息,如命中率、加載失敗次數(shù)等。 - 異步加載:可以使用
getUnchecked或getAll方法進(jìn)行異步加載,適合于耗時(shí)較長(zhǎng)的操作。 - 刷新策略:通過(guò)
refreshAfterWrite方法可以設(shè)置緩存項(xiàng)在寫(xiě)入后的多久時(shí)間后刷新。
5. 注意事項(xiàng)
- 線程安全:Guava Cache是線程安全的,多線程環(huán)境下的讀寫(xiě)操作不需要額外的同步控制。
- 內(nèi)存占用:雖然Guava Cache提供了多種策略來(lái)控制緩存大小,但在高并發(fā)場(chǎng)景下仍需注意內(nèi)存使用情況,避免因內(nèi)存溢出導(dǎo)致應(yīng)用崩潰。
- 過(guò)期策略:合理設(shè)置過(guò)期時(shí)間和清除策略,避免緩存中的數(shù)據(jù)長(zhǎng)時(shí)間不更新,導(dǎo)致數(shù)據(jù)陳舊。
總結(jié)
通過(guò)使用 Guava Cache,我們可以有效地減少對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)次數(shù),提高系統(tǒng)的性能和響應(yīng)速度。特別是在高并發(fā)場(chǎng)景下,緩存的作用更加明顯。希望這個(gè)示例對(duì)你有所幫助!在處理高并發(fā)場(chǎng)景時(shí),緩存是提高系統(tǒng)性能和響應(yīng)速度的重要手段之一。Google Guava庫(kù)提供了一個(gè)非常強(qiáng)大的本地緩存實(shí)現(xiàn)——GuavaCache,它不僅提供了基本的緩存功能,還支持多種高級(jí)特性,如過(guò)期策略、大小限制、統(tǒng)計(jì)信息等,非常適合在高并發(fā)環(huán)境下使用。
到此這篇關(guān)于java中的本地緩存GuavaCache使用方法和示例教程的文章就介紹到這了,更多相關(guān)java本地緩存GuavaCache內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用注解實(shí)現(xiàn)BigDecimal的四舍五入
BigDecimal是Java中的一個(gè)類(lèi),位于java.math包中,它提供了任意精度的有符號(hào)十進(jìn)制數(shù)字的表示,以及對(duì)這些數(shù)字進(jìn)行算術(shù)運(yùn)算的方法,本文介紹了Java使用注解實(shí)現(xiàn)BigDecimal的四舍五入的相關(guān)知識(shí),需要的朋友可以參考下2024-09-09
java判斷中文字符串長(zhǎng)度的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇java判斷中文字符串長(zhǎng)度的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01
Java socket通訊實(shí)現(xiàn)過(guò)程及問(wèn)題解決
這篇文章主要介紹了Java socket通訊實(shí)現(xiàn)過(guò)程及問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01
SpringMVC?RESTFul實(shí)戰(zhàn)案例修改功能實(shí)現(xiàn)
這篇文章主要為大家介紹了SpringMVC?RESTFul實(shí)戰(zhàn)案例修改功能實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05

