Java實(shí)現(xiàn)本地緩存的常用方案介紹
本地緩存
就是和應(yīng)用服務(wù)器一起的緩存工具,將需要緩存的數(shù)據(jù)放到本地緩存中,可以大大的提升訪問速度。
是指和應(yīng)用程序在同一個(gè)進(jìn)程內(nèi)的內(nèi)存空間去存儲數(shù)據(jù),數(shù)據(jù)的讀寫都是在同一個(gè)進(jìn)程內(nèi)完成的。
實(shí)現(xiàn)方式
本地緩存的代表技術(shù)主要有HashMap,Guava Cache,Caffeine和Encahche
- Map:使用 Java 的 Map 集合來實(shí)現(xiàn)本地緩存,將數(shù)據(jù)存儲在內(nèi)存中,以鍵值對的形式進(jìn)行訪問。
- Guava Cache:Google 開源的緩存庫,提供了線程安全的本地緩存實(shí)現(xiàn),支持緩存的自動回收和過期時(shí)間設(shè)置等功能。
- Ehcache:一種輕量級的 Java 緩存框架,可以將數(shù)據(jù)存儲在 JVM 中或者磁盤中,支持緩存的自動回收和過期時(shí)間設(shè)置等功能。
- Caffeine:由 Google 開源的 Java 緩存框架,提供了高性能和可伸縮的緩存實(shí)現(xiàn),支持緩存的自動回收和多種緩存逐出策略等功能。
HashMap
這是最簡單的方式,你可以使用Java的HashMap來存儲緩存數(shù)據(jù)。這種方式在數(shù)據(jù)量小的情況下是可以的。但是如果你需要在多線程環(huán)境下讀寫緩存,那么這種方式可能會引起線程安全問題。
import java.util.HashMap; import java.util.Map; public class SimpleCache { private Map<String, Object> cache = new HashMap<>(); public Object get(String key) { return cache.get(key); } public void put(String key, Object value) { cache.put(key, value); } }
ConcurrentHashMap
ConcurrentHashMap是Java中的一個(gè)線程安全的Map實(shí)現(xiàn),可以在多線程環(huán)境下安全地讀寫緩存。
import java.util.concurrent.ConcurrentHashMap; import java.util.Map; public class ConcurrentCache { private Map<String, Object> cache = new ConcurrentHashMap<>(); public Object get(String key) { return cache.get(key); } public void put(String key, Object value) { cache.put(key, value); } }
Guava Cache
Guava是Google的Java核心庫,提供了強(qiáng)大的緩存功能。它提供了多種緩存策略,例如基于時(shí)間的過期策略、基于大小的淘汰策略等。
import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import java.util.concurrent.TimeUnit; public class GuavaCache { private Cache<String, Object> cache = CacheBuilder.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) // 設(shè)置緩存過期時(shí)間為10分鐘 .maximumSize(1000) // 設(shè)置緩存最大容量為1000個(gè)元素 .build(); public Object get(String key) { return cache.getIfPresent(key); } public void put(String key, Object value) { cache.put(key, value); } }
Caffeine
是基于java8實(shí)現(xiàn)的新一代緩存工具,緩存性能接近理論最優(yōu),可以看作是Guava Cache的增強(qiáng)版,功能上兩者類似,不同的是Caffeine采用了一種結(jié)合LRU、LFU優(yōu)點(diǎn)的算法:W-TinyLFU,在性能上有明顯的優(yōu)越性。
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import java.util.concurrent.TimeUnit; public class LocalCacheExample { public static void main(String[] args) { // 創(chuàng)建一個(gè)基于 Caffeine 的緩存實(shí)例 Cache<String, String> cache = Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) // 設(shè)置緩存過期時(shí)間為10分鐘 .maximumSize(100) // 設(shè)置緩存最大容量為100個(gè)鍵值對 .build(); // 將數(shù)據(jù)放入緩存 cache.put("key1", "value1"); cache.put("key2", "value2"); // 從緩存中獲取數(shù)據(jù) String value1 = cache.getIfPresent("key1"); System.out.println("Value for key1: " + value1); // 緩存中不存在的鍵,返回null String value3 = cache.getIfPresent("key3"); System.out.println("Value for key3: " + value3); // 緩存中不存在的鍵,使用自定義的加載函數(shù)加載數(shù)據(jù)并放入緩存 String value4 = cache.get("key4", key -> "value4"); System.out.println("Value for key4: " + value4); // 手動移除緩存中的數(shù)據(jù) cache.invalidate("key2"); // 清空緩存 cache.invalidateAll(); } }
上述代碼通過 Caffeine.newBuilder() 創(chuàng)建一個(gè)緩存實(shí)例,并使用 expireAfterWrite 設(shè)置緩存過期時(shí)間,使用 maximumSize 設(shè)置緩存的最大容量。然后通過 put 方法將數(shù)據(jù)放入緩存,通過 getIfPresent 方法從緩存中獲取數(shù)據(jù)。如果緩存中不存在指定的鍵,則使用 get 方法并傳入自定義的加載函數(shù)來加載數(shù)據(jù)并放入緩存。可以使用 invalidate 方法手動移除緩存中的數(shù)據(jù),或者使用 invalidateAll 方法清空整個(gè)緩存。
請注意,在使用以上代碼時(shí),需要確保已引入 Caffeine 的相關(guān)依賴項(xiàng),并進(jìn)行相應(yīng)的配置和初始化操作。
Ehcache
下面是使用 Ehcache 實(shí)現(xiàn)本地緩存的示例代碼:
import org.ehcache.Cache; import org.ehcache.CacheManager; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import java.time.Duration; public class LocalCacheExample { public static void main(String[] args) { // 創(chuàng)建一個(gè)基于 Ehcache 的緩存管理器 CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(); cacheManager.init(); // 創(chuàng)建一個(gè)緩存配置 CacheConfiguration<String, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, String.class, ResourcePoolsBuilder.heap(100)) // 設(shè)置緩存最大容量為100個(gè)鍵值對 .withExpiry( CacheConfigurationBuilder.newExpiryPolicyBuilder(Duration.ofMinutes(10))) // 設(shè)置緩存過期時(shí)間為10分鐘 .build(); // 創(chuàng)建一個(gè)緩存實(shí)例 Cache<String, String> cache = cacheManager.createCache("myCache", cacheConfiguration); // 將數(shù)據(jù)放入緩存 cache.put("key1", "value1"); cache.put("key2", "value2"); // 從緩存中獲取數(shù)據(jù) String value1 = cache.get("key1"); System.out.println("Value for key1: " + value1); // 緩存中不存在的鍵,返回null String value3 = cache.get("key3"); System.out.println("Value for key3: " + value3); // 手動移除緩存中的數(shù)據(jù) cache.remove("key2"); // 關(guān)閉緩存管理器 cacheManager.close(); } }
上述代碼通過 CacheManagerBuilder.newCacheManagerBuilder() 創(chuàng)建一個(gè)緩存管理器,并使用 init() 進(jìn)行初始化操作。然后使用 CacheConfigurationBuilder 創(chuàng)建一個(gè)緩存配置,通過 heap 設(shè)置緩存最大容量,通過 withExpiry 設(shè)置緩存過期時(shí)間。接著通過 cacheManager.createCache() 創(chuàng)建一個(gè)緩存實(shí)例,傳入緩存的名稱和緩存配置??梢允褂?put 方法將數(shù)據(jù)放入緩存,使用 get 方法從緩存中獲取數(shù)據(jù),使用 remove 方法手動移除緩存中的數(shù)據(jù)。最后使用 cacheManager.close() 關(guān)閉緩存管理器。
請注意,在使用以上代碼時(shí),需要確保已引入 Ehcache 的相關(guān)依賴項(xiàng),并進(jìn)行相應(yīng)的配置和初始化操作。
實(shí)現(xiàn)方式優(yōu)缺點(diǎn)
HashMap、ConcurrentHashMap、Guava Cache和Caffeine都是Java中常用的緩存實(shí)現(xiàn)方案,它們各自有不同的優(yōu)缺點(diǎn)。
1.HashMap:
優(yōu)點(diǎn):簡單、直接,不需要引入第三方包,適合簡單的場景。
缺點(diǎn):沒有緩存淘汰策略,定制化開發(fā)成本高,且在多線程環(huán)境下可能存在線程安全問題。
2. ConcurrentHashMap:
優(yōu)點(diǎn):線程安全,可以在多線程環(huán)境下安全地讀寫緩存。
缺點(diǎn):相比HashMap,ConcurrentHashMap更加復(fù)雜,且在緩存淘汰策略方面仍然有所限制。
3. Guava Cache:
優(yōu)點(diǎn):功能強(qiáng)大,提供了多種緩存策略,例如基于時(shí)間的過期策略、基于大小的淘汰策略等。性能好,支持異步加載和批量操作。
缺點(diǎn):需要引入Guava庫,且組件的緩存同步需要自己實(shí)現(xiàn)。
4. Caffeine:
優(yōu)點(diǎn):基于Java的高性能緩存庫,提供了內(nèi)存緩存的功能。使用了類似于ConcurrentHashMap的分段鎖機(jī)制,并提供了更多的緩存策略和配置選項(xiàng)。緩存性能接近理論最優(yōu),屬于是Guava Cache的增強(qiáng)版。
缺點(diǎn):需要引入Caffeine庫,且需要一定的學(xué)習(xí)成本。
5.Ehcache:
優(yōu)點(diǎn):支持本地緩存和分布式緩存,提供了豐富的配置選項(xiàng)和緩存策略(如過期時(shí)間、最大大小、持久化等)??梢耘cSpring框架無縫集成。
缺點(diǎn):在高并發(fā)環(huán)境下,性能可能不如Caffeine、Memcached和Redis。分布式緩存功能相對較新,可能不如Redis和Memcached成熟穩(wěn)定。
綜上所述,選擇哪種本地緩存方案取決于具體的需求和場景。如果需求簡單,且不需要考慮線程安全問題,那么HashMap是一個(gè)不錯(cuò)的選擇。如果需要在多線程環(huán)境下讀寫緩存,那么ConcurrentHashMap是一個(gè)更好的選擇。如果需要更強(qiáng)大的緩存功能,例如緩存淘汰策略、異步加載等,那么Guava Cache或Caffeine是一個(gè)不錯(cuò)的選擇。對于需要分布式緩存的場景,Ehcache是一個(gè)不錯(cuò)的選擇。
到此這篇關(guān)于Java實(shí)現(xiàn)本地緩存的常用方案介紹的文章就介紹到這了,更多相關(guān)Java本地緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
elasticsearch索引index之Mapping實(shí)現(xiàn)關(guān)系結(jié)構(gòu)示例
這篇文章主要介紹了elasticsearch索引index之Mapping實(shí)現(xiàn)關(guān)系結(jié)構(gòu)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04Java8使用Stream流實(shí)現(xiàn)List列表查詢、統(tǒng)計(jì)、排序以及分組
List的Stream流操作可以簡化我們的代碼,減少程序運(yùn)行的壓力,應(yīng)對上面的問題,下面這篇文章主要給大家介紹了關(guān)于Java8使用Stream流實(shí)現(xiàn)List列表查詢、統(tǒng)計(jì)、排序以及分組的相關(guān)資料,需要的朋友可以參考下2023-06-06MybatisPlus如何自定義TypeHandler映射JSON類型為List
這篇文章主要介紹了MybatisPlus如何自定義TypeHandler映射JSON類型為List,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01Spring之底層架構(gòu)核心概念Environment及用法詳解
這篇文章主要介紹了Spring之底層架構(gòu)核心概念-Environment,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12