本篇文章給大家分享的是有關(guān)利用Java如何實(shí)現(xiàn)本地緩存,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話(huà)不多說(shuō),跟著小編一起來(lái)看看吧。
創(chuàng)新互聯(lián)建站主要從事網(wǎng)站設(shè)計(jì)制作、做網(wǎng)站、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)撫州,十載網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢(xún)建站服務(wù):028-86922220
使用場(chǎng)景
在 Java
應(yīng)用中,對(duì)于訪(fǎng)問(wèn)頻率高,更新少的數(shù)據(jù),通常的方案是將這類(lèi)數(shù)據(jù)加入緩存中。相對(duì)從數(shù)據(jù)庫(kù)中讀取來(lái)說(shuō),讀緩存效率會(huì)有很大提升。
在集群環(huán)境下,常用的分布式緩存有 redis 、 Memcached 等。但在某些業(yè)務(wù)場(chǎng)景上,可能不需要去搭建一套復(fù)雜的分布式緩存系統(tǒng),在單機(jī)環(huán)境下,通常是會(huì)希望使用內(nèi)部的緩存( LocalCache )。
實(shí)現(xiàn)
這里提供了兩種 LocalCache
的實(shí)現(xiàn),一種是基于 ConcurrentHashMap
實(shí)現(xiàn)基本本地緩存,另外一種是基于 LinkedHashMap
實(shí)現(xiàn) LRU
策略的本地緩存。
基于ConcurrentHashMap的實(shí)現(xiàn)
static { timer = new Timer(); map = new ConcurrentHashMap<>(); }
以 ConcurrentHashMap
作為緩存的存儲(chǔ)結(jié)構(gòu)。因?yàn)?ConcurrentHashMap
的線(xiàn)程安全的,所以基于此實(shí)現(xiàn)的 LocalCache
在多線(xiàn)程并發(fā)環(huán)境的操作是安全的。在 JDK1.8
中, ConcurrentHashMap
是支持完全并發(fā)讀,這對(duì)本地緩存的效率也是一種提升。通過(guò)調(diào)用 ConcurrentHashMap
對(duì) map
的操作來(lái)實(shí)現(xiàn)對(duì)緩存的操作。
私有構(gòu)造函數(shù)
privateLocalCache(){ }
LocalCache
是工具類(lèi),通過(guò)私有構(gòu)造函數(shù)強(qiáng)化不可實(shí)例化的能力。
緩存清除機(jī)制
/** * 清除緩存任務(wù)類(lèi) */ static classCleanWorkerTaskextendsTimerTask{ private String key; publicCleanWorkerTask(String key){ this.key = key; } publicvoidrun(){ LocalCache.remove(key); } }
清理失效緩存是由 Timer 類(lèi)實(shí)現(xiàn)的。內(nèi)部類(lèi) CleanWorkerTask
繼承于 TimerTask
用戶(hù)清除緩存。每當(dāng)新增一個(gè)元素的時(shí)候,都會(huì)調(diào)用 timer.schedule 加載清除緩存的任務(wù)。
基于LinkedHashMap的實(shí)現(xiàn)
以 LinkedHashMap
作為緩存的存儲(chǔ)結(jié)構(gòu)。主要是通過(guò) LinkedHashMap
的按照訪(fǎng)問(wèn)順序的特性來(lái)實(shí)現(xiàn) LRU
策略。
LRU
LRU
是 Least Recently Used
的縮寫(xiě),即最近最久未使用。 LRU 緩存將會(huì)利用這個(gè)算法來(lái)淘汰緩存中老的數(shù)據(jù)元素,從而優(yōu)化內(nèi)存空間。
基于LRU策略的map
這里利用 LinkedHashMap
來(lái)實(shí)現(xiàn)基于 LRU
策略的 map
。通過(guò)調(diào)用父類(lèi) LinkedHashMap
的構(gòu)造函數(shù)來(lái)實(shí)例化 map
。參數(shù) accessOrder
設(shè)置為 true
保證其可以實(shí)現(xiàn) LRU
策略。
static classLRUMapextendsLinkedHashMap { ... // 省略部分代碼 publicLRUMap(intinitialCapacity,floatloadFactor){ super(initialCapacity, loadFactor, true); } ... // 省略部分代碼 /** * 重寫(xiě)LinkedHashMap中removeEldestEntry方法; * 新增元素的時(shí)候,會(huì)判斷當(dāng)前map大小是否超過(guò)DEFAULT_MAX_CAPACITY,超過(guò)則移除map中最老的節(jié)點(diǎn); * * @param eldest * @return */ protectedbooleanremoveEldestEntry(Map.Entry eldest){ return size() > DEFAULT_MAX_CAPACITY; } }
線(xiàn)程安全
/** * 讀寫(xiě)鎖 */ private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final Lock rLock = readWriteLock.readLock(); private final Lock wLock = readWriteLock.writeLock();
LinkedHashMap
并不是線(xiàn)程安全,如果不加控制的在多線(xiàn)程環(huán)境下使用的話(huà),會(huì)有問(wèn)題。所以在 LRUMap
中引入了 ReentrantReadWriteLock
讀寫(xiě)鎖,來(lái)控制并發(fā)問(wèn)題。
緩存淘汰機(jī)制
protectedbooleanremoveEldestEntry(Map.Entryeldest){ return size() > DEFAULT_MAX_CAPACITY; }
此處重寫(xiě) LinkedHashMap
中 removeEldestEntry
方法, 當(dāng)緩存新增元素的時(shí)候,會(huì)判斷當(dāng)前 map
大小是否超過(guò) DEFAULT_MAX_CAPACITY
,超過(guò)則移除map中最老的節(jié)點(diǎn)。
緩存清除機(jī)制
緩存清除機(jī)制與 ConcurrentHashMap
的實(shí)現(xiàn)一致,均是通過(guò) timer
實(shí)現(xiàn)。
以上就是利用Java如何實(shí)現(xiàn)本地緩存,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。