关键词:
缓存主要为了解决各个组件之间读取速度不匹配问题,比如寄存器是L1的缓存,L1是L2的缓存,L2是L3的缓存,L3是内存的缓存等。通过读Java Concurrency Practice P85,实现了一个简单可以添加和获取数据的缓存。其它的诸如缓存过期,更新缓存等没有实现- -!!
代码
计算接口,用到了装饰者模式。
public interface Computable<A,V>
V compute(A arg);
一种计算的实现
public class ExpensiveFunction implements Computable<String,BigInteger>
@Override
public BigInteger compute(String arg)
// 经过长时间计算后
try
Thread.sleep(500000);
catch (InterruptedException ie)
return new BigInteger(arg);
版本1
通过HashMap时间复杂度为O(1)的特性以及synchronized保证线程安全来构建缓存
public class MyCacheV1<A,V> implements Computable<A,V>
private Map<A,V> cache = new HashMap<>();
private Computable computable;
public MyCacheV1(Computable computable)
this.computable = computable;
@Override
public synchronized V compute(A arg)
V result = cache.get(arg);
if (result == null)
result = (V)computable.compute(arg);
cache.put(arg,result);
return result;
版本2
版本1添加了synchronized,多线程情况下造成性能下降 -> 换成ConcurrentHashMap
public class MyCacheV2<A,V> implements Computable<A,V>
private Map<A,V> cache = new ConcurrentHashMap<>();
private Computable computable;
public MyCacheV2(Computable computable)
this.computable = computable;
@Override
public V compute(A arg)
V result = cache.get(arg);
if (result == null)
result = (V)computable.compute(arg);
cache.put(arg,result);
return result;
版本3
版本2先判断 -> 在计算属于复合操作而且没有加锁导致线程不安全会产生重读计算。如果遇到计算时间非常长的计算,一旦重复会消耗大量的资源。
解决思路:如果其他线程正在计算目标值,当前线程阻塞直到其它线程计算出结果返回即可。
实现:通过FutureTask的get()方法。如果没有结果,会阻塞当前线程。
public class MyCacheV3<A,V> implements Computable<A,V>
private Map<A,FutureTask> cache = new ConcurrentHashMap<>();
private Computable computable;
public MyCacheV3(Computable computable)
this.computable = computable;
@Override
public V compute(A arg)
Future future = cache.get(arg);
if (future == null)
FutureTask futureTask = new FutureTask(new Callable()
@Override
public V call() throws Exception
return (V)computable.compute(arg);
);
// 用到了ConcurrentHashMap的原子操作
future = cache.putIfAbsent(arg,futureTask);
// 二次判断
if (future == null) future = futureTask; futureTask.run();
V result = null;
try
result = (V) future.get();
catch (InterruptedException e)
e.printStackTrace();
catch (ExecutionException e)
e.printStackTrace();
return result;
面试官:redis如何实现每周热评功能?说说思路!(代码片段)
思路分析做每周热议,应该用缓存来做,如果直接查库的话,会对数据库造成压力。用缓存做的话,用Redis来做缓存的话比较合适一点。#利用Redsi添加数据命令#day:1指的是在1号的时候post:1第一篇文章添加了10条评... 查看详情
编程实践关于应用层的本地内存缓存框架的代码实现(代码片段)
文章目录用golang实现一个线程安全的本地缓存框架,给出具体的代码实例。一、准备工作1.1定义必要的数据结构二、实现逻辑2.1设置缓存项2.2获取缓存项2.3删除缓存项用Java实现一个线程安全的本地缓存框架,给出具体的代码实... 查看详情
基于信号量与环形队列实现读写异步缓存队列(代码片段)
...思路三、示例代码一、需求 实现一个读写异步的缓存队列,主要实现功能如下: 1、缓存队列作为临界资源,要是线程安全的,不会出现读线程与写线程同时操作缓存队列的情况发生。 2、当缓... 查看详情
redis缓存简介以及缓存的更新策略(代码片段)
目录一、什么是缓存二、为什么要使用缓存三、如何使用缓存四、添加商户缓存1、缓存模型和思路 2、代码如下五、缓存更新策略 1、数据库缓存不一致解决方案: 2、数据库和缓存不一致采用什么方案3、CacheAsidePattern实现... 查看详情
java从零开始手写redislru缓存淘汰策略详解(代码片段)
前言java从零手写实现redis(一)如何实现固定大小的缓存?java从零手写实现redis(三)redisexpire过期原理java从零手写实现redis(三)内存数据如何重启不丢失?java从零手写实现redis(四)添加监听器java从零手写实现redis(五)过... 查看详情
java实现lru缓存算法(代码片段)
Java实现LRU缓存算法 一、什么是LRULRU(LeastRecentlyUsed,最近最少使用)是一种缓存算法,其核心思想是将最近最少使用的缓存项移除,以便为更常用的缓存项腾出空间。在实际应用中,LRU算法被广泛用于缓存和页面置换。 ... 查看详情
react实现网站换肤功能(代码片段)
...主题色的样式文件; 2.将用户的选择记录在本地缓存中; 3.每次进入应用时,读取缓存,根据缓存的信息判断要加载哪个样式文件即可;三.具体实现思路1.准备四个对应不同主题色的样式文件:![](https://images2018 查看详情
elasticsearchelasticsearch缓存策略querycacheingpolicy(代码片段)
1.概述在ES里,QueryCacheingPolicy的默认实现是UsageTrackingQueryCachingPolicy。该Policy的基本思路是根据使用频率决定是否缓存。对于构建成本较高的索引,比如MultiTermQuery,MultiTermQueryConstantScoreWrapper,TermInSetQuery 查看详情
假装优雅地实现定时缓存装饰器(代码片段)
...工匠:使用装饰器的技巧一日一技:实现有过期时间的LRU缓存这次的参考资料写在前面,因为写得真不错!开始阅读本篇分享前,建议先阅读参考资料,如果还不能实现定时缓存装饰器,再继续从这里开始读。实现思路功能拆分... 查看详情
lru基本介绍及其实现方式(代码片段)
...eee85f0203001e9bc34f65b4参考LRU算法dubbo-cache一.基本介绍1.1常见缓存淘汰算法及其实现思路对于缓存,常见淘汰算法有3:FIFO:firstinfirstout,先进先出,即假定刚刚加入的数据总会被访问到;LRU:leastrecentlyused,最近最少使用, 查看详情
排行榜的简单设计思路(代码片段)
前言基于mysqlSELECTORDERBY加索引加缓存借助redis实时排行榜实现原理为什么Redis要用跳表来实现有序集合,而不是红黑树?参考TOC前言排行榜几乎已经成为互联网应用中的必备模块,特别是游戏领域,它是对某一相关同类事物的客... 查看详情
mysql的查询缓存参数介绍与优化思路(代码片段)
...实数据,可以自己做个计算还是挺有趣的!查询缓存的参数说明(my.cnf)mysql>showglobalvariableslike"query_cache%";Va 查看详情
基于信号量与环形队列实现读写异步缓存队列(代码片段)
...思路三、示例代码一、需求 实现一个读写异步的缓存队列,主要实现功能如下: 1、缓存队列作为临界资源,要是线程安全的,不会出现读线程与写线程同时操作缓存队列的情况发生。 2、当缓... 查看详情
场景应用:自己设计一个本地缓存(代码实现)(代码片段)
...5.线程安全6.简明的接口7.是否持久化8.阻塞机制代码实战缓存元素CacheElement实现清除策略LRULinkedHashMap实现缓存接口MyCache实现我的本地缓存实现MyLocalCache实现代码测试想要设计一 查看详情
场景应用:自己设计一个本地缓存(代码实现)(代码片段)
...5.线程安全6.简明的接口7.是否持久化8.阻塞机制代码实战缓存元素CacheElement实现清除策略LRULinkedHashMap实现缓存接口MyCache实现我的本地缓存实现MyLocalCache实现代码测试想要设计一 查看详情
lru实现缓存(代码片段)
LRU:LeastRecentlyused最近最少使用 1.使用LinkedHashMap实现inheritance实现方式继承map类可以使用Collections.synchronizedMap方式实现线程安全的操作publicclassLruCache<K,V>extendsLinkedHashMap<K,V>privatefinalintMAX_CACH 查看详情
.netcorewebapi利用iactionfilter实现请求缓存(代码片段)
.NetCoreWebAPI利用IActionFilter实现请求缓存本文使用Redis缓存方式1新建类首先新建一个缓存类CustomActionCacheAttribute继承Attribute,因为需要给方法做标记。再引用并实现IActionFilter接口publicclassCustomActionCacheAttribute:Attribute,IActionFilter 查看详情