Java設(shè)計(jì)實(shí)現(xiàn)一個(gè)針對(duì)各種類型的緩存
1. 設(shè)計(jì)頂層接口
// 定義為一個(gè)泛型接口,提供給抽象類使用 public interface CacheManager<T> { // 獲取所有的緩存item List<T> getAll(); // 根據(jù)條件獲取某些緩存item List<T> get(Predicate<T> predicate); // 設(shè)置緩存 boolean set(T t); // 設(shè)置緩存list boolean set(List<T> tList); }
有接口必定有實(shí)現(xiàn)類或者抽象類,實(shí)現(xiàn)接口。
那為了更好地控制子類的行為,可以做一個(gè)抽象類,控制子類行為。
分析:
- 抽象類作為緩存管理的話,那么就需要提供安全訪問(wèn)數(shù)據(jù)
- 需要考慮線程安全問(wèn)題。
- 花絮: 不僅要滿足上述需求,而且讓代碼盡量簡(jiǎn)潔。
2. 設(shè)計(jì)抽象類 – AbstractCacheManager
屬性設(shè)計(jì):
- 需要一個(gè)緩存
- 需要一個(gè)線程安全機(jī)制方案
行為設(shè)計(jì):
自己的行為:
- 利用線程安全機(jī)制控制緩存的讀寫(xiě)。
- 權(quán)限:僅自己可訪問(wèn)
后代的行為:
- 訪問(wèn)一些簡(jiǎn)單api方法即可實(shí)現(xiàn)安全訪問(wèn)緩存
- 權(quán)限:公共訪問(wèn)
設(shè)計(jì)模式:
包裹思想,將后代行為方法中,包裹一層安全訪問(wèn)的行為。
Java Code:
// properties design: protected ConcurrentMap<String, T> cache; private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); // subclass to implements these abstract methods. protected abstract List<T> getAllByCache(); protected abstract void setByCache(T t); protected abstract void setByCache(List<T> tList); protected abstract List<T> getByCache(Predicate<T> predicate); // next content needs to consider safety of multithreads. following methods do implements. // entry to use @Override public final List<T> getAll() { return this.readLockThenGet(() -> this.getAllByCache()); } @Override public final List<T> get(Predicate<T> predicate) { return this.readLockThenGet(pre -> getByCache(pre), predicate); } @Override public final boolean set(T t) { return this.writeLockThenSet((Consumer<T>) obj -> set(obj), t); } @Override public final boolean set(List<T> tList) { return this.writeLockThenSet((Consumer<List<T>>) list -> set(list), tList); } // current abstract class access cache object. private boolean writeLockThenSet(Consumer consumer, Object object){ boolean wLock = false; try { if (!(wLock = lock.writeLock().tryLock(100, TimeUnit.MICROSECONDS))) { return false; } consumer.accept(object); return true; } catch (Exception e) { return false; } finally { if(wLock) { lock.writeLock().unlock(); } } } private List<T> readLockThenGet(Supplier<List<T>> supplier){ boolean rLock = false; try{ if(!(rLock = lock.readLock().tryLock(100, TimeUnit.MICROSECONDS))){ return null; } return supplier.get(); }catch (Exception e){ return null; }finally { if(rLock) { lock.readLock().unlock(); } } } private List<T> readLockThenGet(Function<Predicate<T>, List<T>> function, Predicate<T> predicate){ boolean rLock = false; try{ if(!(rLock = lock.readLock().tryLock(100, TimeUnit.MICROSECONDS))){ return null; } return function.apply(predicate); }catch (Exception e){ return null; }finally { if(rLock) { lock.readLock().unlock(); } } }
3. 具體子類
3.1 – AlertRuleItemExpCacheManager
@Component("alertRuleItemExpCacheManager") public class AlertRuleItemExpCacheManager<T extends AlertRuleItemExpCache> extends AbstractCacheManager<AlertRuleItemExpCache> { @Resource private AlertRuleItemExpDao alertRuleItemExpDao; @Override protected List<AlertRuleItemExpCache> getAllByCache() { if (null == cache) { List<AlertRuleItemExp> alertRuleItemSrcList = alertRuleItemExpDao.selectList(Wrappers.<AlertRuleItemExp>lambdaQuery().eq(AlertRuleItemExp::getDeleted, 0)); cache = alertRuleItemSrcList.stream().map(entity -> entity.toCache()) .collect(Collectors.toConcurrentMap(cache -> cache.getId().toString(), cache -> cache)); } return cache.values().stream() .sorted(Comparator.comparing(AlertRuleItemExpCache::getId)) .collect(Collectors.toList()); } @Override protected void setByCache(AlertRuleItemExpCache alertRuleItemExpCache) { cache.put(alertRuleItemExpCache.getId().toString(), alertRuleItemExpCache); } @Override protected void setByCache(List<AlertRuleItemExpCache> alertRuleItemExpCacheList) { alertRuleItemExpCacheList.parallelStream().forEach(alertRuleItemExpCache -> cache.put(alertRuleItemExpCache.getId().toString(), alertRuleItemExpCache)); } @Override protected List<AlertRuleItemExpCache> getByCache(Predicate<AlertRuleItemExpCache> predicate) { return getAllByCache().stream().filter(cache -> predicate.test(cache)).collect(Collectors.toList()); } }
3.2 – AlertRuleItemSrcCacheManager
@Component("alertRuleItemSrcCacheManager") public class AlertRuleItemSrcCacheManager<T extends AlertRuleItemSrcCache> extends AbstractCacheManager<AlertRuleItemSrcCache> { @Resource private AlertRuleItemSrcDao alertRuleItemSrcDao; @Override protected List<AlertRuleItemSrcCache> getAllByCache() { if (null == cache) { List<AlertRuleItemSrc> alertRuleItemSrcList = alertRuleItemSrcDao.selectList(Wrappers.<AlertRuleItemSrc>lambdaQuery().eq(AlertRuleItemSrc::getDeleted, 0)); cache = alertRuleItemSrcList.stream().map(entity -> entity.toCache()) .collect(Collectors.toConcurrentMap(cache -> cache.getId().toString(), cache -> cache)); } return cache.values().stream() .sorted(Comparator.comparing(AlertRuleItemSrcCache::getId)) .collect(Collectors.toList()); } @Override protected void setByCache(AlertRuleItemSrcCache alertRuleItemSrcCache) { cache.put(alertRuleItemSrcCache.getId().toString(), alertRuleItemSrcCache); } @Override protected void setByCache(List<AlertRuleItemSrcCache> alertRuleItemSrcCacheList) { alertRuleItemSrcCacheList.parallelStream().forEach(alertRuleItemSrcCache -> cache.put(alertRuleItemSrcCache.getId().toString(), alertRuleItemSrcCache)); } @Override protected List<AlertRuleItemSrcCache> getByCache(Predicate<AlertRuleItemSrcCache> predicate) { return getAllByCache().stream().filter(cache -> predicate.test(cache)).collect(Collectors.toList()); } }
4. 類圖關(guān)系
以上就是Java設(shè)計(jì)實(shí)現(xiàn)一個(gè)針對(duì)各種類型的緩存的詳細(xì)內(nèi)容,更多關(guān)于Java緩存的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java基本數(shù)據(jù)類型和運(yùn)算符詳解
這篇文章主要介紹了Java基本數(shù)據(jù)類型和運(yùn)算符,結(jié)合實(shí)例形式詳細(xì)分析了java基本數(shù)據(jù)類型、數(shù)據(jù)類型轉(zhuǎn)換、算術(shù)運(yùn)算符、邏輯運(yùn)算符等相關(guān)原理與操作技巧,需要的朋友可以參考下2020-02-02通過(guò)Mybatis實(shí)現(xiàn)單表內(nèi)一對(duì)多的數(shù)據(jù)展示示例代碼
最近做項(xiàng)目遇到這樣的需求要求將表中的數(shù)據(jù),按照一級(jí)二級(jí)分類返回給前端json數(shù)據(jù),下面通過(guò)本文給大家分享通過(guò)Mybatis實(shí)現(xiàn)單表內(nèi)一對(duì)多的數(shù)據(jù)展示示例代碼,感興趣的朋友參考下吧2017-08-08java獲取nvidia顯卡信息的實(shí)現(xiàn)示例
現(xiàn)在的需求是要獲取nvidia顯卡的使用情況,本文主要介紹了java獲取nvidia顯卡信息的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02java?poi之XWPFDocument如何讀取word內(nèi)容并創(chuàng)建新的word
這篇文章主要介紹了java?poi之XWPFDocument如何讀取word內(nèi)容并創(chuàng)建新的word問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04SpringBoot項(xiàng)目里集成Hibernate的示例
在Spring Boot項(xiàng)目中,集成Hibernate可以幫助我們更輕松地進(jìn)行數(shù)據(jù)庫(kù)操作,本文將介紹如何在Spring Boot項(xiàng)目中集成Hibernate,并提供相應(yīng)的示例,感興趣的朋友跟隨小編一起看看吧2023-04-04如何使用Spring Cloud Feign日志查看請(qǐng)求響應(yīng)
這篇文章主要介紹了如何使用Spring Cloud Feign日志查看請(qǐng)求響應(yīng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02java基本教程之java線程等待與java喚醒線程 java多線程教程
這篇文章主要介紹了對(duì)線程等待/喚醒方法,文中使用了多個(gè)示例,大家參考使用吧2014-01-01IntelliJ IDEA 統(tǒng)一設(shè)置編碼為utf-8編碼的實(shí)現(xiàn)
這篇文章主要介紹了IntelliJ IDEA 統(tǒng)一設(shè)置編碼為utf-8編碼的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2020-06-06