Java设计实现一个针对各种类型的缓存
更新时间:2023年11月16日 10:51:08 作者:代码哲学
这篇文章主要为大家详细介绍了Java如何设计实现一个针对各种类型的缓存,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
1. 设计顶层接口
// 定义为一个泛型接口,提供给抽象类使用 public interface CacheManager<T> { // 获取所有的缓存item List<T> getAll(); // 根据条件获取某些缓存item List<T> get(Predicate<T> predicate); // 设置缓存 boolean set(T t); // 设置缓存list boolean set(List<T> tList); }
有接口必定有实现类或者抽象类,实现接口。
那为了更好地控制子类的行为,可以做一个抽象类,控制子类行为。
分析:
- 抽象类作为缓存管理的话,那么就需要提供安全访问数据
- 需要考虑线程安全问题。
- 花絮: 不仅要满足上述需求,而且让代码尽量简洁。
2. 设计抽象类 – AbstractCacheManager
属性设计:
- 需要一个缓存
- 需要一个线程安全机制方案
行为设计:
自己的行为:
- 利用线程安全机制控制缓存的读写。
- 权限:仅自己可访问
后代的行为:
- 访问一些简单api方法即可实现安全访问缓存
- 权限:公共访问
设计模式:
包裹思想,将后代行为方法中,包裹一层安全访问的行为。
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. 类图关系
以上就是Java设计实现一个针对各种类型的缓存的详细内容,更多关于Java缓存的资料请关注脚本之家其它相关文章!
相关文章
关于Mybatis-Plus Wrapper是否应该出现在Servcie类中
最近在做代码重构,代码工程采用了Controller/Service/Dao分层架构,Dao层使用了Mybatis-Plus框架,本文带领大家学习Mybatis-Plus Wrapper应该出现在Servcie类中吗,需要的朋友可以参考下2023-05-05spring boot 2.x静态资源会被拦截器拦截的原因分析及解决
这篇文章主要介绍了spring boot 2.x静态资源会被拦截器拦截的原因分析及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2023-01-01
最新评论